php Memcache缓存队列类

<?php


/**
 * Memcache缓存队列类
 * @author ricky 
*/ 
class CacheMemcacheQueue { 
    public static $client; // memcache客户端连接
    public $access; //队列是否可更新
    private $expire; //过期时间,秒,1〜2592000,即30 天内
    private $sleepTime; //等待解锁时间,微秒
    private $queueName; //队列名称,唯一值
    private $retryNum; //重试次数,= 10 *理论并发数
    public $currentHead; //当前队首值
    public $currentTail; //当前队尾值


    const MAXNUM = 2000; //最大队列数,建议上限10K 
    const HEAD_KEY ='_QueueHead_'; //队列首kye 
    const TAIL_KEY ='_QueueTail_'; // 队列尾键
    const VALU_KEY ='_QueueValu_'; // 队列值key
    const LOCK_KEY ='_QueueLock_'; 


    /**
     *构造函数
     * @param string $queueName队列名称
     * @param int $expire缓存队列生命周期时间
     * @return <type> 
    */ 
    function __construct($queueName,$expire = 0,$config =''){ 
        if(empty($config){ 
           self :: $client = memcache_pconnect('127.0.0.1',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)?3600:intval($expire)+ 1; 
        $this-> expire = $expire; 
        $this-> queueName = $queueName; 
        $this-> retryNum = 1000; 
        $this -> _initSetHeadNTail(); 
    } 
    /**
     *初始化设置队列首尾值
    */ 
    private function _initSetHeadNTail(){ 
        //当前队列首的数值
        $head_key = $this-> queueName.self :: HEAD_KEY; 
        $tail_key = $this-> queueName.self :: TAIL_KEY; 
        $this-> currentHead = self :: $client-> get($head_key); 
        if($this-> currentHead === false)
            $this-> currentHead = 0; 
        //当前队列尾的数值
        $this-> currentTail = self :: $client-> get($tail_key); 
        if($this-> currentTail === false)
            $this-> currentTail = 0; 
    } 
    /**
     *当取出元素时,
     改变队列首的数值* @param int $step步长值
    */ 
    private function _changeHead($step = 1){ 
        $head_key = $this-> queueName.self :: HEAD_KEY; 
        $this-> currentHead + = $step; 
        self :: $client-> set($head_key,$this-> currentHead,false,$this-> expire); 
    } 
    /**
     *当添加元素时,改变队列的数值
     * @param int $step步长值
     * @param bool $reverse是否反向
     * @return null 
    */ 
    private function _changeTail($step = 1,$reverse = false){ 
        $tail_key = $this-> queueName.self :: TAIL_KEY; 
        if(!$reverse){ 
            $this-> currentTail + = $step; 
        } else { 
            $this-> currentTail - = $step; 
        } 
        self :: $client-> set($tail_key,$this-> currentTail,false,$this-> expire); 
    } 
    /**
     *队列是否为空
     * @return bool 
    */ 
    private function _isEmpty(){ 
        return(bool)($this-> currentHead === $this-> currentTail); 
    } 
    /**
     *队列是否已满
     * @return bool 
    */ 
    private function _isFull(){ 
        $len = $this-> currentTail - $this-> currentHead; 
        return(bool)($len === self :: MAXNUM); 
    } 


    /**
     * queue列加锁
    */ 
    private function _getLock(){ 
        $head_key = $this-> queueName.self :: HEAD_KEY; 
        if($this-> access === false){ 
            while($result = self :: $client-> add($head_key,1,MEMCACHE_COMPRESSED,$this-> expire){ 
                usleep($this-> sleepTime) ; 
                $i ++; 
                if($i> $this-> retryNum){//尝试等待N次
                    return false; 
                    打破; 
                } 
            } 
            $this -> _initSetHeadNTail(); 
            return $this-> access = true; 
        } 
        return $this-> access; 
    } 


    /**
     *队列解锁
    */ 
    private function _unLock(){ 
        $lock_key = $this-> queueName.self :: VALU_KEY; 
        self :: $client-> delete($lock_key,0); 
        $this-> access = false; 
    } 


    /**
     *添加队列数据
     * @param void $data要添加的数据
     * @return bool 
    */ 
    public function queueAdd($data){ 
        if(!$this -> _getLock()
            return false; 
        if($this -> _isFull(){ 
            $this -> _unLock(); 
            return false; 
        } 
        $value_key = $this-> queueName.self :: VALU_KEY.strval($this-> currentTail + 1); 
        $result = self :: $client-> set($value_key,$data,MEMCACHE_COMPRESSED,$this-> expire); 
        var_dump($result); 
        if($result){ 
            $this -> _changeTail(); 
        } 
        $this -> _unLock(); 
        return $result; 
    } 
    /**
     * 读取队列数据
     * @param int $length要读取的长度(反向读取使用负数)
     * @return array 
    */ 
    public function queueRead($length = 0){ 
        if(!is_numeric length)
            return false; 
        $this -> _initSetHeadNTail(); 
        if($this -> _isEmpty(){ 
            return false; 
        } 
        if(empty($length)
            $length = self :: MAXNUM; //默认所有
        $keyArr = array(); 
        if($length> 0){//正向读取(从队列首向队列尾)
            $tmpMin = $this-> currentHead; 
            $tmpMax = $tmpMin + $length; 
            for($i = $tmpMin; $i <= $tmpMax; $i ++){ 
                $keyArr [] = $this-> queueName.self :: VALU_KEY.$i; 
            } 
        } else {//反向读取(从队列尾向队列首)
            $tmpMax = $this-> currentTail; 
            $tmpMin = $tmpMax + $length; 
            for($i = $tmpMax; $i> $tmpMin; 
                $i-- ){ $keyArr [] = $this-> queueName.self :: VALU_KEY.$i; 
            } 
        } 
        $result = self :: $client-> get($keyArr); 
        return $result; 
    } 


    /**
     *取出队列数据
     * @param int $length要取出的长度(反向读取使用负数)
     * @return array 
    */ 
    public function queueGet($length = 0){ 
        if(!is_numeric($length) )
            return false; 
        if(!$this -> _getLock()
            return false; 


        if($this -> _isEmpty(){ 
            $this -> _unLock(); 
            return false; 
        } 
        if(empty($length)
            $length = self :: MAXNUM; //默认所有
        $length = intval($length); 
        $keyArr = array(); 
        if($length> 0){//正向读取(从队列首向队列尾)
            $tmpMin = $this-> currentHead; 
            $tmpMax = $tmpMin + $length; 
            for($i = $tmpMin; $i <= $tmpMax; $i ++){ 
                $keyArr [] = $this-> queueName.self :: VALU_KEY.$i; 
            } 
            $this -> _changeHead($length); 
        } else {//反向读取(从队列尾向队列首)
            $tmpMax = $this-> currentTail; 
            $tmpMin = $tmpMax + $length; 
            for($i = $tmpMax; $i> $tmpMin; 
                $i-- ){ $keyArr [] = $this-> queueName.self :: VALU_KEY.$i; 
            } 
            $this -> _changeTail(abs($length),true); 
        } 
        $result = self :: $client-> get($keyArr); 
        foreach($keyArr as $v){//取出之后删除
            self :: $client-> delete($v,0); 
        } 
        $this -> _unLock(); 
        return $result; 
    } 
    /**
     *清空队列
    */ 
    public function queueClear(){ 
        $head_key = $this-> queueName.self :: HEAD_KEY; 
        $tail_key = $this-> queueName.self :: TAIL_KEY; 
        if(!$this -> _getLock()return false; 
            
        if($this-> 
            _isEmpty(){ $this -> _unLock(); 
            return false; 
        } 
        $tmpMin = $this-> currentHead--; 
        $tmpMax = $this-> currentTail ++; 
        for($i = $tmpMin; $i <= $tmpMax; $i ++){ 
            $tmpKey = $this-> queueName.self :: VALU_KEY.$i; 
            // memcache_delete(self :: $client,$tmpKey,0); 
            self :: $client-> delete($tmpKey,0); 
        } 
        $this-> currentTail = $this-> currentHead = 0; 
        self :: $client-> set($head_key,$this-> currentHead,false,$this-> expire); 
        self :: $client-> set($tail_key,$this-> currentTail,false,$this-> expire); 
        $this -> _unLock(); 
    } 


    /*
     *清除所有memcache缓存数据
    */ 


    public function memFlush(){ 
        // memcache_flush(self :: $client); 
        self :: $client-> flush(); 
    } 
    
    /*
     *单一删除缓存
    */ 
    public function queueDelete($key){ 
        $head_key = $this-> queueName.self :: HEAD_KEY; 
        $tail_key = $this-> queueName.self :: TAIL_KEY; 
        if(!$this -> _getLock()return false; 
            
        if($this -> _isEmpty(){ 
            $this -> _unLock(); 
            return false; 
        } 
        $tmpMin = $this-> currentHead--; 
        $tmpMax = $this-> currentTail ++; 
        for($i = $tmpMin; $i <= $tmpMax; $i ++){ 
            $tmpKey = $key.$i; 
            self :: $client-> delete($tmpKey,0); 
        } 
        $this-> currentTail = $this-> currentHead = 0; 
        self :: $client-> set($head_key,$this-> currentHead,false,$this-> expire); 
        self :: $client-> set($tail_key,$this-> currentTail,false,$this-> expire); 
        $this -> _unLock(); 
        return true; 
    } 


} 
        self :: $client-> set($head_key,$this-> currentHead,false,$this-> expire); 
        self :: $client-> set($tail_key,$this-> currentTail,false,$this-> expire); 
        $this -> _unLock(); return true; 
    } } 
        self :: $client-> set($head_key,$this-> currentHead,false,$this-> expire); 
        self :: $client-> set($tail_key,$this-> currentTail,false,$this-> expire); 
        $this -> _unLock(); return true;
     } }

文章来源: php Memcache缓存队列类

人吐槽 人点赞

猜你喜欢

发表评论

用户名: 密码:
验证码: 匿名发表

你可以使用这些语言

查看评论:php Memcache缓存队列类