0

0

php自己实现memcached的队列类_PHP教程

php中文网

php中文网

发布时间:2016-07-13 09:54:51

|

923人浏览过

|

来源于php中文网

原创

php自己实现memcached的队列类

 

聚好用AI
聚好用AI

可免费AI绘图、AI音乐、AI视频创作,聚集全球顶级AI,一站式创意平台

下载

 

<!--?php
/*
 * memcache队列类
 * 支持多进程并发写入、读取
 * 边写边读,AB面轮值替换
 * @author guoyu
 * @create on 9:25 2014-9-28
 * @qq技术行业交流群:136112330
 *
 * @example:
 *      $obj = new memcacheQueue('duilie');
 *      $obj--->add('1asdf');
 *      $obj->getQueueLength();
 *      $obj->read(11);
 *      $obj->get(8);
 */

class memcacheQueue{
    public static   $client;            //memcache客户端连接
    public          $access;            //队列是否可更新   
    private         $currentSide;       //当前轮值的队列面:A/B
    private         $lastSide;          //上一轮值的队列面:A/B
    private         $sideAHead;         //A面队首值
    private         $sideATail;         //A面队尾值
    private         $sideBHead;         //B面队首值
    private         $sideBTail;         //B面队尾值
    private         $currentHead;       //当前队首值
    private         $currentTail;       //当前队尾值
    private         $lastHead;          //上轮队首值
    private         $lastTail;          //上轮队尾值 
    private         $expire;            //过期时间,秒,1~2592000,即30天内;0为永不过期
    private         $sleepTime;         //等待解锁时间,微秒
    private         $queueName;         //队列名称,唯一值
    private         $retryNum;          //重试次数,= 10 * 理论并发数

    const   MAXNUM      = 2000;                 //(单面)最大队列数,建议上限10K
    const   HEAD_KEY    = '_lkkQueueHead_';     //队列首kye
    const   TAIL_KEY    = '_lkkQueueTail_';     //队列尾key
    const   VALU_KEY    = '_lkkQueueValu_';     //队列值key
    const   LOCK_KEY    = '_lkkQueueLock_';     //队列锁key
    const   SIDE_KEY    = '_lkkQueueSide_';     //轮值面key

    /*
     * 构造函数
     * @param   [config]    array   memcache服务器参数
     * @param   [queueName] string  队列名称
     * @param   [expire]    string  过期时间
     * @return  NULL
     */
    public function __construct($queueName ='',$expire='',$config =''){
        if(empty($config)){
            self::$client = memcache_pconnect('localhost',11211);
        }elseif(is_array($config)){//array('host'=>'127.0.0.1','port'=>'11211')
            self::$client = memcache_pconnect($config['host'],$config['port']);
        }elseif(is_string($config)){//"127.0.0.1:11211"
            $tmp = explode(':',$config);
            $conf['host'] = isset($tmp[0]) ? $tmp[0] : '127.0.0.1';
            $conf['port'] = isset($tmp[1]) ? $tmp[1] : '11211';
            self::$client = memcache_pconnect($conf['host'],$conf['port']);     
        }
        if(!self::$client) return false;

        ignore_user_abort(TRUE);//当客户断开连接,允许继续执行
        set_time_limit(0);//取消脚本执行延时上限

        $this->access = false;
        $this->sleepTime = 1000;
        $expire = (empty($expire) && $expire!=0) ? 3600 : (int)$expire;
        $this->expire = $expire;
        $this->queueName = $queueName;
        $this->retryNum = 10000;

        $side = memcache_add(self::$client, $queueName . self::SIDE_KEY, 'A',false, $expire);
        $this->getHeadNTail($queueName);
        if(!isset($this->sideAHead) || empty($this->sideAHead)) $this->sideAHead = 0;
        if(!isset($this->sideATail) || empty($this->sideATail)) $this->sideATail = 0;
        if(!isset($this->sideBHead) || empty($this->sideBHead)) $this->sideBHead = 0;
        if(!isset($this->sideBHead) || empty($this->sideBHead)) $this->sideBHead = 0;
    }

    /*
     * 获取队列首尾值
     * @param   [queueName] string  队列名称
     * @return  NULL
     */
    private function getHeadNTail($queueName){
        $this->sideAHead = (int)memcache_get(self::$client, $queueName.'A'. self::HEAD_KEY);
        $this->sideATail = (int)memcache_get(self::$client, $queueName.'A'. self::TAIL_KEY);
        $this->sideBHead = (int)memcache_get(self::$client, $queueName.'B'. self::HEAD_KEY);
        $this->sideBTail = (int)memcache_get(self::$client, $queueName.'B'. self::TAIL_KEY);
    }

    /*
     * 获取当前轮值的队列面
     * @return  string  队列面名称
     */
    public function getCurrentSide(){
        $currentSide = memcache_get(self::$client, $this->queueName . self::SIDE_KEY);
        if($currentSide == 'A'){
            $this->currentSide = 'A';
            $this->lastSide = 'B';  

            $this->currentHead  = $this->sideAHead;
            $this->currentTail  = $this->sideATail;
            $this->lastHead     = $this->sideBHead;
            $this->lastTail     = $this->sideBTail;         
        }else{
            $this->currentSide = 'B';
            $this->lastSide = 'A';

            $this->currentHead  = $this->sideBHead;
            $this->currentTail  = $this->sideBTail;
            $this->lastHead     = $this->sideAHead;
            $this->lastTail     = $this->sideATail;                     
        }

        return $this->currentSide;
    }

    /*
     * 队列加锁
     * @return boolean
     */
    private function getLock(){
        if($this->access === false){
            while(!memcache_add(self::$client, $this->queueName .self::LOCK_KEY, 1, false, $this->expire) ){
                usleep($this->sleepTime);
                @$i++;
                if($i > $this->retryNum){//尝试等待N次
                    return false;
                    break;
                }
            }
            return $this->access = true;
        }
        return false;
    }

    /*
     * 队列解锁
     * @return NULL
     */
    private function unLock(){
        memcache_delete(self::$client, $this->queueName .self::LOCK_KEY);
        $this->access = false;
    }

    /*
     * 添加数据
     * @param   [data]  要存储的值
     * @return  boolean
     */
    public function add($data){
        $result = false;
        if(!$this->getLock()){
            return $result;
        } 
        $this->getHeadNTail($this->queueName);
        $this->getCurrentSide();

        if($this->isFull()){
            $this->unLock();
            return false;
        }

        if($this->currentTail < self::MAXNUM){
            $value_key = $this->queueName .$this->currentSide . self::VALU_KEY . $this->currentTail;
            if(memcache_add(self::$client, $value_key, $data, false, $this->expire)){
                $this->changeTail();
                $result = true;
            }
        }else{//当前队列已满,更换轮值面
            $this->unLock();
            $this->changeCurrentSide();
            return $this->add($data);
        }

        $this->unLock();
        return $result;
    }

    /*
     * 取出数据
     * @param   [length]    int 数据的长度
     * @return  array
     */
    public function get($length=0){
        if(!is_numeric($length)) return false;
        if(empty($length)) $length = self::MAXNUM * 2;//默认读取所有
        if(!$this->getLock()) return false;

        if($this->isEmpty()){
            $this->unLock();
            return false;
        }

        $keyArray   = $this->getKeyArray($length);
        $lastKey    = $keyArray['lastKey'];
        $currentKey = $keyArray['currentKey'];
        $keys       = $keyArray['keys'];
        $this->changeHead($this->lastSide,$lastKey);
        $this->changeHead($this->currentSide,$currentKey);

        $data   = @memcache_get(self::$client, $keys);
        foreach($keys as $v){//取出之后删除
            @memcache_delete(self::$client, $v, 0);
        }
        $this->unLock();

        return $data;
    }

    /*
     * 读取数据
     * @param   [length]    int 数据的长度
     * @return  array
     */
    public function read($length=0){
        if(!is_numeric($length)) return false;
        if(empty($length)) $length = self::MAXNUM * 2;//默认读取所有
        $keyArray   = $this->getKeyArray($length);
        $data   = @memcache_get(self::$client, $keyArray['keys']);
        return $data;
    }

    /*
     * 获取队列某段长度的key数组
     * @param   [length]    int 队列长度
     * @return  array
     */
    private function getKeyArray($length){
        $result = array('keys'=>array(),'lastKey'=>array(),'currentKey'=>array());
        $this->getHeadNTail($this->queueName);
        $this->getCurrentSide();
        if(empty($length)) return $result;

        //先取上一面的key
        $i = $result['lastKey'] = 0;
        for($i=0;$i<$length;$i++){
            $result['lastKey'] = $this->lastHead + $i;
            if($result['lastKey'] >= $this->lastTail) break;
            $result['keys'][] = $this->queueName .$this->lastSide . self::VALU_KEY . $result['lastKey'];
        }

        //再取当前面的key
        $j = $length - $i;
        $k = $result['currentKey'] = 0;
        for($k=0;$k<$j;$k++){
            $result['currentKey'] = $this->currentHead + $k;
            if($result['currentKey'] >= $this->currentTail) break;
            $result['keys'][] = $this->queueName .$this->currentSide . self::VALU_KEY . $result['currentKey'];
        }

        return $result;
    }

    /*
     * 更新当前轮值面队列尾的值
     * @return  NULL
     */
    private function changeTail(){
        $tail_key = $this->queueName .$this->currentSide . self::TAIL_KEY;
        memcache_add(self::$client, $tail_key, 0,false, $this->expire);//如果没有,则插入;有则false;
        //memcache_increment(self::$client, $tail_key, 1);//队列尾+1
        $v = memcache_get(self::$client, $tail_key) +1;
        memcache_set(self::$client, $tail_key,$v,false,$this->expire);
    }

    /*
     * 更新队列首的值
     * @param   [side]      string  要更新的面
     * @param   [headValue] int     队列首的值
     * @return  NULL
     */
    private function changeHead($side,$headValue){
        if($headValue < 1) return false;
        $head_key = $this->queueName .$side . self::HEAD_KEY;
        $tail_key = $this->queueName .$side . self::TAIL_KEY;
        $sideTail = memcache_get(self::$client, $tail_key);
        if($headValue < $sideTail){
            memcache_set(self::$client, $head_key,$headValue+1,false,$this->expire);
        }elseif($headValue >= $sideTail){
            $this->resetSide($side);
        }
    }

    /*
     * 重置队列面,即将该队列面的队首、队尾值置为0
     * @param   [side]  string  要重置的面
     * @return  NULL
     */
    private function resetSide($side){
        $head_key = $this->queueName .$side . self::HEAD_KEY;
        $tail_key = $this->queueName .$side . self::TAIL_KEY;
        memcache_set(self::$client, $head_key,0,false,$this->expire);
        memcache_set(self::$client, $tail_key,0,false,$this->expire);
    }

    /*
     * 改变当前轮值队列面
     * @return  string
     */
    private function changeCurrentSide(){
        $currentSide = memcache_get(self::$client, $this->queueName . self::SIDE_KEY);
        if($currentSide == 'A'){
            memcache_set(self::$client, $this->queueName . self::SIDE_KEY,'B',false,$this->expire);
            $this->currentSide = 'B';
        }else{
            memcache_set(self::$client, $this->queueName . self::SIDE_KEY,'A',false,$this->expire);
            $this->currentSide = 'A';
        }
        return $this->currentSide;
    }

    /*
     * 检查当前队列是否已满
     * @return  boolean
     */
    public function isFull(){
        $result = false;
        if($this->sideATail == self::MAXNUM && $this->sideBTail == self::MAXNUM){
            $result = true;
        }
        return $result;
    }

    /*
     * 检查当前队列是否为空
     * @return  boolean
     */
    public function isEmpty(){
        $result = true;
        if($this->sideATail > 0 || $this->sideBTail > 0){
            $result = false;
        }
        return $result;
    }

    /*
     * 获取当前队列的长度
     * 该长度为理论长度,某些元素由于过期失效而丢失,真实长度小于或等于该长度
     * @return  int
     */
    public function getQueueLength(){
        $this->getHeadNTail($this->queueName);
        $this->getCurrentSide();

        $sideALength = $this->sideATail - $this->sideAHead;
        $sideBLength = $this->sideBTail - $this->sideBHead;
        $result = $sideALength + $sideBLength;

        return $result;
    }

    /*
     * 清空当前队列数据,仅保留HEAD_KEY、TAIL_KEY、SIDE_KEY三个key
     * @return  boolean
     */
    public function clear(){
        if(!$this->getLock()) return false;
        for($i=0;$i<self::maxnum;$i++){ this-="">queueName.'A'. self::VALU_KEY .$i, 0);
            @memcache_delete(self::$client, $this->queueName.'B'. self::VALU_KEY .$i, 0);
        }
        $this->unLock();
        $this->resetSide('A');
        $this->resetSide('B');
        return true;
    }

    /*
     * 清除所有memcache缓存数据
     * @return  NULL
     */
    public function memFlush(){
        memcache_flush(self::$client);
    }

}
</self::maxnum;$i++){>


 

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/994954.htmlTechArticlephp自己实现memcached的队列类 add(1asdf); * $obj-getQueueLength(); * $obj-read(11); * $obj-get(8); */class memcacheQueue{ public static $client; //memcache客户端连接 pu...

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

49

2026.03.13

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

89

2026.03.12

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

276

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

59

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

99

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

105

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

230

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

619

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

173

2026.03.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号