zoukankan      html  css  js  c++  java
  • PHP Redis锁

    一、什么是 Redis

    Redis是由意大利人Salvatore Sanfilippo(网名:antirez)开发的一款内存高速缓存数据库

    二、什么是 Redis 分布式锁

    分布式锁其实可以理解为:控制分布式系统有序的去对共享资源进行操作,通过互斥来保持一致性。 举个不太恰当的例子:假设共享的资源就是一个房子,里面有各种书,分布式系统就是要进屋看书的人,分布式锁就是保证这个房子只有一个门并且一次只有一个人可以进,而且门只有一把钥匙。然后许多人要去看书,可以,排队,第一个人拿着钥匙把门打开进屋看书并且把门锁上,然后第二个人没有钥匙,那就等着,等第一个出来,然后你在拿着钥匙进去,然后就是以此类推

    三、Redis 锁使用场景

    1. 数据高并发的读写

    2. 海量数据的读写

    3. 对扩展性要求高的数据

    四、代码实现

    基于Yii 1.2

    <?php
    namespace commonsase;
    use Redis;
    
    /**
     *  Redis锁操作类,防止并发访问
     */
    class RedisLock
    {
        private static $_instance = null;
    
        /**
         * @var Redis
         */
        private $_redis;
    
        //key前缀
        private $_lockPrefix = "common_base_lock:";
    
        public function __construct()
        {
            $this->_redis = Redis::getInstance();
        }
    
        public static function getInstance()
        {
            if(self::$_instance == null)
            {
                self::$_instance = new RedisLock();
            }
            return self::$_instance;
        }
    
        /**
         * 加锁
         * @param string $key      -加锁的key
         * @param int $wait        -锁等待时间,秒
         * @param int $expire      -锁失效时间,秒
         * @return boolean
         * 获取锁成功返回
         */
        public function lock($key,$wait=1,$expire=5)
        {
            $hasWait = 0;//已经等待的时间:毫秒
            do
            {
                $getLock = $this->_redis->setNx($this->_getKeyName($key),1,$expire);//通过setNx获取锁,只有一个能拿到
                if(!$getLock)//没拿到锁
                {
                    if($hasWait > $wait*1000)//等待超时
                    {
                        return false;
                    }
                    usleep(30000);//等待30ms
                    $hasWait += 30;
                    continue;
                }
                return true;
            }
            while(true);
        }
    
        /**
         * 加锁, 非阻塞, 获取锁失败或者成功直接返回
         * @param string $key      -加锁的key
         * @param int $expire      -锁失效时间,秒
         * @return boolean
         * 获取锁成功返回
         */
        public function NBLock($key, $expire=5)
        {
            return  $this->_redis->setNx($this->_getKeyName($key),1,$expire);//通过setNx获取锁,只有一个能拿到
        }
    
        /**
         * 释放锁
         * @param string $key    -锁的key
         * @return boolean
         */
        public function unlock($key)
        {
            return $this->_redis->delete($this->_getKeyName($key));
        }
    
        private function _getKeyName($key)
        {
            return $this->_lockPrefix . $key;
        }
    }
    <?php
    namespace datalevels;
    use baseConfig;
    use baseLogger;
    
    /**
     * redis
     * 兼容yii cache接口,可以使用Yii::app()->cache->get() 形式使用
     * 也可以使用: Redis::getInstance()->get() 形式使用
     * 推荐使用Redis::getInstance()形式,Yii::app()->cache只是为了兼容YII框架处理,redis接口远比yii框架的cache接口丰富。
     */
    class Redis extends CCache
    {
        /**
         * 无穷大
         * @var string
         */
        const  MAX_VALUE = '+inf';
    
        /**
         * 无穷小
         * @var string
         */
        const  MIN_VALUE = '-inf';
    
        /**
         * 聚合类型,求和
         * @var string
         */
        const AGGREGATE_TYPE_SUM = 'SUM';
    
        /**
         * 聚合类型,最大值
         * @var string
         */
        const AGGREGATE_TYPE_MAX = 'MAX';
    
        /**
         * 聚合类型,最小值
         * @var string
         */
        const AGGREGATE_TYPE_MIN = 'MIN';
    
        /**
         * redis
         * @var Redis
         */
        private static $_instance = null;
    
        /**
         * redis链接
         * @var Redis
         */
        private $_redis = null;
    
        private $_conf = array();
    
        public function __construct()
        {
            $this->_conf = Config::getInstance()->get("", 'redis');
            if (empty($this->_conf) || !isset($this->_conf['host']) || !isset($this->_conf['port'])) {
                throw new DaoException("redis config invalid.");
            }
            try{
                if (!$this->_connect()) {
                    throw new DaoException("connect to redis failure");
                }
            } catch (RedisException $e) {
                Logger::error("connect to redis failure.");
                throw new DaoException("connect to redis failure");
            }
        }
    
        /**
         * 获取redis实例
         * @return Redis
         */
        public static function getInstance()
        {
            if (null === self::$_instance) {
                self::$_instance = new Redis();
            }
            return self::$_instance;
        }
    /**
         * Get the value related to the specified key
         * @param string $key
         * @return String or Bool: If key didn't exist, FALSE is returned. Otherwise, the value related to this key is returned.
         */
        public function get($key)
        {
            return $this->_redis->get($key);
        }
    
    
        /**
         * Get the values of all the specified keys. If one or more keys dont exist, the array will contain FALSE at the position of the key.
         * @param array $keys       - key数组
         * @return Array: Array containing the values related to keys in argument
         */
        public function mget($keys)
        {
            return $this->_redis->mget($keys);
        }
    
        /**
         * Set the string value in argument as value of the key
         * @param string $key
         * @param mixed $value        -   任意值
         * @param int $expire         -   过期时间,单位秒
         * @return bool 成功返回true
         */
        public function set($key, $value, $expire = 0, $dependency = null)
        {
            if ($expire > 0) {
                return $this->_redis->set($key, $value, $expire);
            }
            return $this->_redis->set($key, $value);
        }
    
        /**
         * 设置key值,如果key存在则失败
         * @param string $key
         * @param mixed $value        -   任意值
         * @param int $expire         -   过期时间,单位秒
         * @return bool 成功返回true, key存在返回false
         */
        public function setNx($key, $value, $expire = 0)
        {
            $ret = $this->_redis->setNx($key, $value);
            if (true === $ret && $expire > 0) {
                $this->_redis->setTimeout($key, $expire);
            }
            return $ret;
        }
    
        /**
         * Verify if the specified key exists.
         * @param string $key
         * @return BOOL: If the key exists, return TRUE, otherwise return FALSE.
         */
        public function exists($key)
        {
            return $this->_redis->exists($key);
        }
    
        /**
         * Sets a value and returns the previous entry at that key.
         * @param string $key
         * @param mixed $value        -   任意值
         * @param int $expire         -   过期时间,单位秒
         */
        public function getSet($key, $value, $expire = 0)
        {
            $prev = $this->_redis->getSet($key, $value);
            if ($expire > 0) {
                $this->_redis->setTimeout($key, $expire);
            }
            return $prev;
        }
    
        /**
         *  增加key 的值
         * @param string $key
         * @param number $step      - 增加步长,每次加多少
         * @param int $expire            - 超时时间
         * @return int   最新值
         */
        public function incr($key, $step = 1, $expire = 0)
        {
            $ret = false;
            if ($step > 1) {
                $ret =  $this->_redis->incrBy($key, $step);
            }
            else {
                $ret = $this->_redis->incr($key);
            }
    
            if (false !== $ret && $expire > 0) {
                $this->_redis->setTimeout($key, $expire);
            }
            return $ret;
        }
    
        /**
         *  减少key 的值
         * @param string $key
         * @param number $step      - 减少步长,每次减多少
         * @param int $expire            - 超时时间
         * @return int   最新值
         */
        public function decr($key, $step = 1, $expire = 0)
        {
            $ret = false;
            if ($step > 1) {
                $ret =  $this->_redis->decrBy($key, $step);
            }
            else {
                $ret = $this->_redis->decr($key);
            }
    
            if (false !== $ret && $expire > 0) {
                $this->_redis->setTimeout($key, $expire);
            }
            return $ret;
        }
    
    
    
        /**
         * Remove specified keys.
         * @param string $key           - 批量删除,传递key数组
         * @return mixed - Long Number of keys deleted.
         */
        public function delete($key)
        {
            return $this->_redis->delete($key);
        }
    
        /**
         * 重命名key
         * @param $srcKey       - 原key
         * @param $dstKey       - 改名后的key
         * @return bool     - 成功返回true
         */
        public function rename($srcKey, $dstKey)
        {
            return $this->_redis->rename($srcKey, $dstKey);
        }
    
        /**
         * 设置key超时时间,单位秒
         * @param string $key            - 设置key超时时间
         * @param int $expire            - 不限制设置-1
         * @return bool 成功返回true
         */
        public function setTimeout($key, $expire)
        {
            return $this->_redis->setTimeout($key, $expire);
        }
    
        /**
         * 获取该key在redis里的剩余存活时间,单位秒
         * @param string $key     -key
         * @return int|false      -成功返回时间
         */
        public function ttl($key)
        {
            $restTime=$this->_redis->ttl($key);
            if($restTime>=0)
            {
                return $restTime;
            }
            else
            {
                return false;
            }
        }
    
        /**
         * hash表操作 - 删除hash字段
         * @param string  $key
         * @param string $field  - hash字段
         * @return LONG the number of deleted keys, 0 if the key doesn't exist, FALSE if the key isn't a hash.
         */
        public function hDel($key, $field)
        {
            return $this->_redis->hDel($key, $field);
        }
    
        /**
         * hash表操作 - 检测hash 字段是否存在
         * @param string  $key
         * @param string $field   - hash字段
         * @return BOOL: If the member exists in the hash table, return TRUE, otherwise return FALSE.
         */
        public function hExists($key, $field)
        {
            return $this->_redis->hExists($key, $field);
        }
    
        /**
         * hash表操作 - 获取hash字段的值
         * @param string  $key
         * @param string $field    - 字段
         * @return mixed | false    - 成功返回值,失败返回false
         */
        public function hGet($key, $field)
        {
            return json_decode($this->_redis->hGet($key, $field), true);
        }
    
        /**
         * hash表操作 - 获取hash表中所有字段值
         * @param string  $key
         * @return array
         */
        public function hGetAll($key)
        {
            return $this->_redis->hGetAll($key);
        }
    
        /**
         * hash表操作 - 增加hash字段的数值
         * @param string  $key
         * @param string $field   - hash字段
         * @param number $step      - 增加步长,每次加多少
         * @param int $expire            - 超时时间
         * @return LONG 返回新值
         */
        public function hIncrBy($key, $field, $step = 1, $expire = 0)
        {
            $ret = $this->_redis->hIncrBy($key, $field, $step);
            if (false !== $ret && $expire > 0) {
                $this->_redis->setTimeout($key, $expire);
            }
            return $ret;
        }
    
        /**
         * hash表操作 - 返回全部hash字段
         * @param string $key
         * @return array
         */
        public function hKeys($key)
        {
            return $this->_redis->hKeys($key);
        }
    
        /**
         * hash表操作 - 返回hash的字段数
         * @param string $key
         * @return int key不存在返回false
         */
        public function hLen($key)
        {
            return $this->_redis->hLen($key);
        }
    
        /**
         * hash表操作 - 批量获取hash的字段值
         * @param string $key
         * @param array $fields       -    hash字段
         * @return boolean|mixed
         */
        public function hMGet($key, array $fields)
        {
            if (empty($fields)) {
                return false;
            }
            return $this->_redis->hMget($key, $fields);
        }
    
        /**
         * hash表操作 - 批量设置hash字段值
         * @param string $key
         * @param array $fields         -   hash字段数组, 例:array('uid' => 1, 'name' => 'lewaimai')
         * @param int $expire             -   过期时间,单位秒
         * @return bool 成功返回true
         */
        public function hMSet($key, array $fields, $expire = 0)
        {
            if (empty($fields)) {
                return false;
            }
            $ret = $this->_redis->hMset($key, $fields);
            if (false !== $ret && $expire > 0) {
                $this->_redis->setTimeout($key, $expire);
            }
            return $ret;
        }
    
        /**
         * hash表操作 - 设置hash字段值
         * @param string $key
         * @param string $field         -   hash字段
         * @param mixed $value                 - 任意值
         * @param int $expire                 -   过期时间,单位秒
         * @return bool 成功返回true
         */
        public function hSet($key, $field, $value, $expire = 0)
        {
            $ret = $this->_redis->hSet($key, $field, $value);
            if (false !== $ret && $expire > 0) {
                $this->_redis->setTimeout($key, $expire);
            }
            return $ret;
        }
    
        /**
         * hash表操作 - 设置hash字段值, 如果字段存在则失败。
         * @param string $key
         * @param string $field         -   hash字段
         * @param mixed $value                 - 任意值
         * @param int $expire                 -   过期时间,单位秒
         * @return bool 成功返回true, hash字段已经存在
         */
        public function hSetNx($key, $field, $value, $expire = 0)
        {
            $ret = $this->_redis->hSetNx($key, $field, $value);
            if (true === $ret && $expire > 0) {
                $this->_redis->setTimeout($key, $expire);
            }
            return $ret;
        }
    
        /**
         * list操作 - 获取指定位置的元素
         * @param string $key
         * @param int $index            - 索引位置从0开始, -1代表最后一个
         * @return mixed | false     -成功返回结果,失败返回false
         */
        public function lGet($key, $index)
        {
            return $this->_redis->lGet($key, $index);
        }
    
        /**
         * list操作 - 在指定元素之前或之后插入元素
         * @param string $key
         * @param mixed $pivot            - 参考元素,在该元素之前或者之后插入, 如果该元素不存在,则放弃插入
         * @param mixed $value            - 待插入元素
         * @param int $posType    - 插入类型,Redis::BEFORE 或则 Redis::AFTER
         * @return int  成功返回list元素个数,失败返回-1表示$pivot不存在。
         */
        public function lInsert($key,  $pivot, $value, $posType = Redis::AFTER)
        {
            return $this->_redis->lInsert($key, $posType, $pivot, $value);
        }
    
        /**
         * list操作 - 根据范围 [$start, $end] 获取元素
         * 例如:获取全部数据的范围条件 [0, -1]
         * @param string $key
         * @param int $start        - 开始位置
         * @param int $end        - 结束位置
         * @return array
         */
        public function lRange($key, $start, $end)
        {
            return $this->_redis->lRange($key, $start, $end);
        }
    
        /**
         * list操作 - 返回list元素个数
         * @param string $key
         * @return int | false 成功返回元素个数,失败返回false
         */
        public function lSize($key)
        {
            return $this->_redis->lSize($key);
        }
    
        /**
         * list操作 - 从head弹出一个元素
         * @param string $key
         * @return mixed | false 成功返回元素,失败或则为空返回false
         */
        public function lPop($key)
        {
            return $this->_redis->lPop($key);
        }
    
        /**
         * list操作 - 从head插入一个元素, list不存在则创建
         * @param string $key
         * @param mixed $value        - 元素
         * @param int $expire        - 超时时间,0不限制
         * @return int | false 成功返回list元素个数
         */
        public function lPush($key, $value, $expire = 0)
        {
            $ret = $this->_redis->lPush($key, $value);
            if (false !== $ret && $expire > 0) {
                $this->_redis->setTimeout($key, $expire);
            }
            return $ret;
        }
    
        /**
         * list操作 - 从head插入一个元素, list不存在则放弃写入
         * @param string $key
         * @param mixed $value        - 元素
         * @param int $expire        - 超时时间,0不限制
         * @return int | false 成功返回list元素个数
         */
        public function lPushx($key, $value)
        {
            return $this->_redis->lPushx($key, $value);
        }
    
        /**
         * list操作 - 从list中删除前面$count个$value元素
         * @param string $key
         * @param string $value        - 待删除元素, 从head开始查找
         * @param int $count                - 需要删除几个元素, 0则全部删除
         * @return int | false    成功返回删除元素个数
         */
        public function lRem($key, $value, $count)
        {
            return $this->_redis->lRem($key, $value, $count);
        }
    
        /**
         * list操作 - 设置list指定位置的值
         * @param string $key
         * @param int $index            - 索引,从0开始
         * @param mixed $value
         * @param int $expire        - 超时时间,0不限制
         * @return bool 成功返回true
         */
        public function lSet($key, $index, $value, $expire = 0)
        {
            $ret =  $this->_redis->lSet($key, $index, $value);
            if (false !== $ret && $expire > 0) {
                $this->_redis->setTimeout($key, $expire);
            }
            return $ret;
        }
    
        /**
         * list操作 - 根据范围缩小list数据
         * @param string $key
         * @param int $start            - 开始索引
         * @param int $stop            - 结束索引
         * @return bool 成功返回true
         */
        public function lTrim($key, $start, $stop)
        {
            return $this->_redis->lTrim($key, $start, $stop);
        }
    
        /**
         * list操作 - 从表尾弹出元素
         * @param string $key
         * @return mixed | false 成功返回元素,失败或则为空返回false
         */
        public function rPop($key)
        {
            return $this->_redis->rPop($key);
        }
    
        /**
         * list操作 - 从表尾插入一个元素, list不存在则创建
         * @param string $key
         * @param mixed $value        - 元素
         * @param int $expire        - 超时时间,0不限制
         * @return int | false 成功返回list元素个数
         */
        public function rPush($key, $value, $expire = 0)
        {
            $ret = $this->_redis->rPush($key, $value);
            if (false !== $ret && $expire > 0) {
                $this->_redis->setTimeout($key, $expire);
            }
            return $ret;
        }
    
        /**
         * list操作 - 从表尾插入一个元素, list不存在则放弃写入
         * @param string $key
         * @param mixed $value        - 元素
         * @return int | false 成功返回list元素个数
         */
        public function rPushX($key, $value)
        {
            return $this->_redis->rPushX($key, $value);
        }
    
        /**
         * 集合操作 - 添加元素, 如果元素已经存在返回false
         * @param string $key
         * @param string $value        - 允许批量写入,传入数组即可,批量写入,只要有一个元素插入失败则返回false
         * @param int $expire            - 超时时间, 0不限制
         * @return int | false 成功返回集合元素个数,失败返回false
         */
        public function sAdd($key, $value, $expire = 0)
        {
            $ret = false;
            if (!empty($value) && is_array($value)) {
                $params = [$key];
                $params = array_merge($params, $value);
                $ret = call_user_func_array(array($this->_redis, 'sAdd'), $params);
            } else {
                $ret = $this->_redis->sAdd($key, $value);
            }
    
            if ($ret && $expire > 0) {
                $this->_redis->setTimeout($key, $expire);
            }
            return $ret ? true : false;
        }
    
        /**
         * 集合操作 - 返回所有集合元素
         * @param string $key
         * @return array
         */
        public function sMembers($key)
        {
            return $this->_redis->sMembers($key);
        }
    
        /**
         * 集合操作 - 检测集合是否包含指定元素
         * @param string $key
         * @param mixed $value
         * @return bool    存在返回true
         */
        public function sIsMember($key, $value)
        {
            return $this->_redis->sIsMember($key, $value);
        }
    
        /**
         *  集合操作 - 返回集合元素个数, key不存在返回0
         * @param string $key
         * @return int
         */
        public function sSize($key)
        {
            return $this->_redis->sSize($key);
        }
    
        /**
         * 集合操作 - 将一个元素从一个集合移动到另外一个集合
         * @param string $srcKey        - 源集合
         * @param string $dstKey        - 目标集合
         * @param mixed $member        - 待移动元素
         * @return bool 成功返回true
         */
        public function sMove($srcKey, $dstKey, $member)
        {
            return $this->_redis->sMove($srcKey, $dstKey, $member);
        }
    
        /**
         * 集合操作 - 随机弹出一个集合元素
         * @param string $key
         * @return mixed | false        - 成功返回集合元素,失败返回false
         */
        public function sPop($key)
        {
            return $this->_redis->sPop($key);
        }
    
        /**
         * 集合操作 - 随机获取一个元素,不删除该元素
         * @param string $key
         * @param int $count        - 随机返回多少个元素
         * @return mixed |false        - 如果$count=1则返回一个元素,$count > 1则返回一个元素数组
         */
        public function sRandMember($key, $count = 1)
        {
            $ret = false;
            if ($count > 1) {
                $ret = $this->_redis->sRandMember($key, $count);
                //bug处理,srandmember没有反序列化数据
                if (!empty($ret)) {
                    foreach ($ret as $k => $v) {
                        $ret[$k] = unserialize($v);
                    }
                }
            }
            else {
                $ret = unserialize($this->_redis->sRandMember($key));
            }
            return $ret;
        }
    
        /**
         * 集合操作 - 计算key1的差集, 允许传递N个参数,最少传递2个参数
         * @param string $key1
         * @param string $key2
         * @return boolean|array 成功返回array, 失败返回false
         */
        public function sDiff($key1, $key2)
        {
            if (func_num_args() < 2) {
                return false;
            }
            return call_user_func_array([$this->_redis, "sDiff"], func_get_args());
        }
    
        /**
         * 集合操作 - 计算key1的差集, 允许传递N个参数,最少传递3个参数, 结果保存在$dstKey
         * @param string $dstKey   - 结果保存在该key
         * @param string $key1
         * @param string $key2
         * @return boolean|int 成功返回$dstKey集合元素个数, 失败返回false
         */
        public function sDiffStore($dstKey, $key1, $key2)
        {
            if (func_num_args() < 3) {
                return false;
            }
            return call_user_func_array([$this->_redis, "sDiffStore"], func_get_args());
        }
    
        /**
         * 集合操作 - 计算交集, 允许传递N个参数,最少传递2个参数,只要参与交集运算其中的一个集合key不存在,则返回false
         * @param string $key1
         * @param string $key2
         * @return boolean|array 成功返回array, 失败返回false
         */
        public function sInter($key1, $key2)
        {
            if (func_num_args() < 2) {
                return false;
            }
            return call_user_func_array([$this->_redis, "sInter"], func_get_args());
        }
    
        /**
         * 集合操作 - 计算交集, 允许传递N个参数,最少传递3个参数,只要参与交集运算其中的一个集合key不存在,则返回false
         * @param string $dstKey   - 结果保存在该key
         * @param string $key1
         * @param string $key2
         * @return boolean|int 成功返回$dstKey集合元素个数, 失败返回false
         */
        public function sInterStore($dstKey, $key1, $key2)
        {
            if (func_num_args() < 3) {
                return false;
            }
            return call_user_func_array([$this->_redis, "sInterStore"], func_get_args());
        }
    
        /**
         * 集合操作 - 删除集合元素
         * @param string $key
         * @param mixed $member        - 集合元素, 支持批量删除,传递数组即可
         * @return int 返回删除元素个数
         */
        public function sRem($key, $member)
        {
            if (!empty($member) && is_array($member)) {
                $params = [$key];
                $params = array_merge($params, $member);
                return call_user_func_array([$this->_redis, 'sRem'], $params);
            }
            return $this->_redis->sRem($key, $member);
        }
    
        /**
         * 集合操作 - 计算并集, 允许传递N个参数,最少传递2个参数
         * @param string $key1
         * @param string $key2
         * @return boolean|array 成功返回array, 失败返回false
         */
        public function sUnion($key1, $key2)
        {
            if (func_num_args() < 2) {
                return false;
            }
            return call_user_func_array([$this->_redis, "sUnion"], func_get_args());
        }
    
        /**
         * 集合操作 - 计算并集, 允许传递N个参数,最少传递3个参数
         * @param string $dstKey   - 结果保存在该key
         * @param string $key1
         * @param string $key2
         * @return boolean|int 成功返回$dstKey集合元素个数, 失败返回false
         */
        public function sUnionStore($dstkey, $key1, $key2)
        {
            if (func_num_args() < 2) {
                return false;
            }
            return call_user_func_array([$this->_redis, "sUnionStore"], func_get_args());
        }
    
        /**
         * 有序集合操作    - 添加元素
         * @param string $key
         * @param mixed $value
         * @param double $score        - 元素权值
         * @param int $expire            - 超时时间, 0不限制
         * @return bool 成功返回true
         */
        public function zAdd($key, $value, $score, $expire = 0)
        {
            $ret = $this->_redis->zAdd($key, $score, $value);
            if ($ret && $expire > 0) {
                $this->setTimeout($key, $expire);
            }
            return $ret ? true : false;
        }
    
    /**
         * 有序集合操作    - 批量添加元素
         * @param string $key
         * @param array $value        -     集合元素数组,格式: ["元素1" => "权值", "元素2" => "权值"]
         * @param int $expire            - 超时时间, 0不限制
         * @return bool 成功返回true
         */
        public function zAdds($key, array $values, $expire = 0)
        {
            if (empty($values) || !is_array($values)) {
                return false;
            }
            $params = [$key];
            foreach ($values as $k => $score) {
                $params[] = $score;
                $params[] = $k;
            }
            $ret = call_user_func_array([$this->_redis, 'zAdd'], $params);
            if ($ret && $expire > 0) {
                $this->setTimeout($key, $expire);
            }
             return $ret ? true : false;
        }
    
        /**
         * 有序集合操作    - 返回集合元素个数
         * @param string $key
         * @return int
         */
        public function zSize($key)
        {
            return $this->_redis->zSize($key);
        }
    
        /**
         * 有序集合操作 - 统计权值在[$start, $end]之间的元素个数
         * @param string $key
         * @param string $start            - 权值最小值,  支持无穷小, Redis::MIN_VALUE
         * @param string $end            - 权值最大值, 支持无穷大, Redis::MAX_VALUE
         * @return int
         */
        public function zCount($key, $start, $end)
        {
            return $this->_redis->zCount($key, $start, $end);
        }
    
        /**
         * 有序集合操作 - 指定元素的增加权值
         * @param string $key
         * @param mixed $member        - 集合元素
         * @param double $score        - 需要增加的权值
         * @param int $expire            - 超时时间, 0不限制
         * @return int  成功返回新的权值
         */
        public function zIncrBy($key, $member, $score, $expire = 0)
        {
            $ret = $this->_redis->zIncrBy($key, $score, $member);
            if (false !== $ret && $expire > 0) {
                $this->setTimeout($key, $expire);
            }
            return $ret;
        }
    
        /**
         * 有序集合操作 - 返回[start, end]索引区间的元素, 升序排序
         * @param string $key
         * @param int $start        - 开始索引
         * @param int $end        - 结束索引, -1代表最后一个
         * @return array | false 成功返回集合元素数组,格式: ["元素1" => 权值, "元素2" => 权值 ...]
         */
        public function zRange($key, $start, $end)
        {
            return $this->_redis->zRange($key, $start, $end, true);
        }
    
        /**
         * 有序集合操作 - 返回[start, end]索引区间的元素, 反序排序
         * @param string $key
         * @param int $start        - 开始索引
         * @param int $end        - 结束索引, -1代表最后一个
         * @return array | false 成功返回集合元素数组,格式: ["元素1" => 权值, "元素2" => 权值 ...]
         */
        public function zRevRange($key, $start, $end)
        {
            return $this->_redis->zRevRange($key, $start, $end, true);
        }
    
    
    
        /**
         * 有序集合操作 - 交集运算,合并相同元素权值时采用如下策略:
         * 1. $weights为空, 则权值相加,$aggregateType设置无效
         * 2. $weights不为空,且$weights数组大小必须与$keys数组大小一致,否则失败。
         *     这种情况下,首先$keys数组中的每一个集合的元素权值分别乘于$weights对应的权值,然后根据$aggregateType确定相加,取最大值或则最小值.
         *        例子:
         *            //创建有序集合,zuser_list1
         *            Redis::getInstance()->zAdds("zuser_list1", [
         *                                                                                    //元素 => 权值
         *                                                                                    1 => 10,
         *                                                                                    2 => 5,
         *                                                                                    3 => 13,
         *                                                                                    6 => 1,
         *                                                                                    9 => 2,
         *                                                                                    10 => 1,
         *                                                                                ]);
         *            //创建有序集合,zuser_list2
         *            Redis::getInstance()->zAdds("zuser_list2", [
         *                                                                                    1 => 10,
         *                                                                                    2 => 5,
         *                                                                                    3 => 13,
         *                                                                                    60 => 1,
         *                                                                            ]);
         *            //    集合zuser_list1和zuser_list2做交集运算, 结果保存在zuser_dst中
         *            Redis::getInstance()->zInter("zuser_dst", array("zuser_list1", "zuser_list2"), [1,10], Redis::AGGREGATE_TYPE_SUM);
         *            //结果为:[
         *                                 //元素 => 权值
         *                                  2 => 55,
         *                                  1 => 110,
         *                                  3 => 143,
         *                                 ]
         *             //计算过程:
         *             首先 zuser_list1和zuser_list2直接做交集运算,遇到相同的元素按下面规则处理
         *             因为$weights权值数组为: [1, 10], 因此zuser_list1集合每个元素的权值乘于 1,  zuser_list2集合每个元素的权值乘于 10
         *             因为$aggregateType = Redis::AGGREGATE_TYPE_SUM, 所以相同元素权值相加。
         *
         * @param string $dstKey                                - 结果保存在该key
         * @param array $keys                                    - 需要做交集运算的集合key数组
         * @param array $weights                            - 权值数组,必须与keys数组的大小一致,要么就为空
         * @param string $aggregateType                - 相同元素的权值聚合类型,Redis::AGGREGATE_TYPE_SUM 求和
         *                                                                                                               Redis::AGGREGATE_TYPE_MAX 取最大值
         *                                                                                                               Redis::AGGREGATE_TYPE_MIN  取最小值
         * @return int 成功返回$dstKey结果元素个数
         */
        public function zInter($dstKey, array $keys, array $weights = [], $aggregateType = self::AGGREGATE_TYPE_SUM)
        {
            if (empty($weights)) {
                return $this->_redis->zInter($dstKey, $keys);
            }
            return $this->_redis->zInter($dstKey, $keys, $weights, $aggregateType);
        }
    
        /**
         * 有序集合操作 - 返回权值区间 [start,end]的集合元素, 权值按小到大排序
         * @param string $key
         * @param string $start            - 权值最小值,  支持无穷小, Redis::MIN_VALUE
         * @param string $end            - 权值最大值, 支持无穷大, Redis::MAX_VALUE
         * @param int $offset                - 开始偏移
         * @param int $count                - 分页大小
         * @return array | false   格式:[
         *                                                             "元素1" => 权值,
         *                                                             "元素2" => 权值,
         *                                                                 ....
         *                                                          ]
         */
        public function zRangeByScore($key, $start, $end, $offset = 0, $count = 0)
        {
            if ($offset >= 0 && $count > 0) {
                return $this->_redis->zRangeByScore($key, $start, $end, ['withscores' => true, 'limit' => [$offset, $count]]);
            }
            return $this->_redis->zRangeByScore($key, $start, $end, ['withscores' => true]);
        }
    
        /**
         * 有序集合操作 - 返回权值区间 [start,end]的集合元素, 权值按大到小排序
         * @param string $key
         * @param string $start            - 权值最小值,  支持无穷小, Redis::MIN_VALUE
         * @param string $end            - 权值最大值, 支持无穷大, Redis::MAX_VALUE
         * @param int $offset                - 开始偏移
         * @param int $count                - 分页大小
         * @return array | false   格式:[
         *                                                             "元素1" => 权值,
         *                                                             "元素2" => 权值,
         *                                                                 ....
         *                                                          ]
         */
        public function zRevRangeByScore($key, $start, $end, $offset = 0, $count = 0)
        {
            if ($offset >= 0 && $count > 0) {
                return $this->_redis->zRevRangeByScore($key, $end, $start, ['withscores' => true, 'limit' => [$offset, $count]]);
            }
            return $this->_redis->zRevRangeByScore($key, $end, $start, ['withscores' => true]);
        }
    
        /**
         * 有序集合操作 - 假定集合元素权值相等的情况下,集合元素按字典顺序查找
         * 例子:
         *         //查找小于等于y的集合元素
         *         Redis::getInstance()->zRangeByLex("key1", "-", "[y")
         *         //查找大于c的元素
         *         Redis::getInstance()->zRangeByLex("key1", "(c", "+")
         *
         * @param string $key
         * @param string $min            - 字母最小值,- 表示负无穷,( 表示大于,[ 表示大于等于
         * @param string $max            - 字母最大值, + 表示正无穷,( 表示大于,[ 表示大于等于
         * @param int $offset                - 元素开始偏移
         * @param int $count                - 分页大小
         * @return
         */
        public function zRangeByLex($key, $min, $max, $offset = 0, $count = 0)
        {
            if ($offset >= 0 && $count > 0) {
                return $this->_redis->zRangeByLex($key, $min, $max, $offset, $count);
            }
            return $this->_redis->zRangeByLex($key, $min, $max);
        }
    
        /**
         * 有序集合操作 - 查找正序排名,从0开始计算名次
         * @param string $key
         * @param mixed $member        - 集合元素
         * @return int | false 成功返回名次
         */
        public function zRank($key, $member)
        {
            return $this->_redis->zRank($key,$member);
        }
    
        /**
         * 有序集合操作 - 查找反序排名,从0开始计算名次
         * @param string $key
         * @param mixed $member        - 集合元素
         * @return int | false 成功返回名次
         */
        public function zRevRank($key, $member)
        {
            return $this->_redis->zRevRank($key,$member);
        }
    
        /**
         * 有序集合操作 - 删除集合元素
         * @param string $key
         * @param mixed $member        - 集合元素, 支持批量删除,传递数组即可
         * @return int 返回删除元素个数
         */
        public function zRem($key, $member)
        {
            if (!empty($member) && is_array($member)) {
                $params = [$key];
                $params = array_merge($params, $member);
                return call_user_func_array([$this->_redis, 'zRem'], $params);
            }
            return $this->_redis->zRem($key, $member);
        }
    
        /**
         * 有序集合操作 - 删除这个名次区间[start,end]的元素, 按升序排序
         * @param string $key
         * @param int $start
         * @param int $end
         * @return int | false 成功返回删除元素个数
         */
        public function zRemRangeByRank($key, $start, $end)
        {
            return $this->_redis->zRemRangeByRank($key, $start, $end);
        }
    
        /**
         * 有序集合操作 - 删除这个权值区间[start,end]的元素
         * @param string $key
         * @param string $start            - 权值最小值,  支持无穷小, Redis::MIN_VALUE
         * @param string $end            - 权值最大值, 支持无穷大, Redis::MAX_VALUE
         * @return int | false 成功返回删除元素个数
         */
        public function zRemRangeByScore($key, $start, $end)
        {
            return $this->_redis->zRemRangeByScore($key, $start, $end);
        }
    
        /**
         * 有序集合操作 - 获取指定元素的权值
         * @param string $key
         * @param string $member            - 元素
         * @return double | false 成功返回权值,失败返回false
         */
        public function zScore($key, $member)
        {
            return $this->_redis->zScore($key, $member);
        }
    
        /**
         * 有序集合操作 - 并集运算,遇到相同元素合并权值策略,请参考zInter交集权值合并策略。
         * @param string $dstKey                                - 结果保存在该key
         * @param array $keys                                    - 需要做并集运算的集合key数组
         * @param array $weights                            - 权值数组,必须与keys数组的大小一致,要么就为空
         * @param string $aggregateType                - 相同元素的权值聚合类型,Redis::AGGREGATE_TYPE_SUM 求和
         *                                                                                                               Redis::AGGREGATE_TYPE_MAX 取最大值
         *                                                                                                               Redis::AGGREGATE_TYPE_MIN  取最小值
         * @return int 成功返回$dstKey结果元素个数
         */
        public function zUnion($dstKey, array $keys, array $weights = [], $aggregateType = self::AGGREGATE_TYPE_SUM)
        {
            if (empty($weights)) {
                return $this->_redis->zUnion($dstKey, $keys);
            }
            return $this->_redis->zUnion($dstKey, $keys, $weights, $aggregateType);
        }
    
        /**
         * {@inheritDoc}
         * @see CCache::addValue()
         */
        protected function addValue($key, $value, $expire)
        {
            return $this->setNx($key, $value, $expire);
        }
    
        /**
         * {@inheritDoc}
         * @see CCache::deleteValue()
         */
        protected function deleteValue($key)
        {
            return $this->delete($key);
        }
    
        /**
         * {@inheritDoc}
         * @see CCache::flushValues()
         */
        protected function flushValues()
        {
            //不支持,禁用
            return true;
        }
    
        /**
         * {@inheritDoc}
         * @see CCache::generateUniqueKey()
         */
        protected function generateUniqueKey($key)
        {
            return $key;
        }
    
        /**
         * {@inheritDoc}
         * @see CCache::getValue()
         */
        protected function getValue($key)
        {
            return $this->get($key);
        }
    
        /**
         * {@inheritDoc}
         * @see CCache::getValues()
         */
        protected function getValues($keys)
        {
            return $this->mget($keys);
        }
    
        /**
         * {@inheritDoc}
         * @see CCache::setValue()
         */
        protected function setValue($key, $value, $expire)
        {
            return $this->set($key, $value, $expire);
        }
      /**
         * 连接redis
         */
        private function _connect()
        {
            if (null === $this->_redis) {
                $this->_redis = new Redis();
            }
    
            $ret = false;
            if (true == $this->_conf['persistent']) {
                $ret = $this->_redis->pconnect($this->_conf['host'], $this->_conf['port'], $this->_conf['timeout']);
            } else {
                $ret = $this->_redis->connect($this->_conf['host'], $this->_conf['port'], $this->_conf['timeout']);
            }
    
            //密码不为空, 则需要密码验证
            if (!empty($this->_conf['password'])) {
                $ret = $this->_redis->auth($this->_conf['password']);
            }
    
            //序列化
            $this->_redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP);
            return $ret;
        }
    }
  • 相关阅读:
    ubuntu下搭建lnmp
    mysql常用命令
    nginx 配置 location 语法 正则表达式
    网站策划方案写作、演示标准[转]
    WEB3.0标准的核心
    也谈论坛“BBS2.0”的十大升级方向 [网摘]
    未来网站策划呈现5大趋势 [网摘]
    关于Web 2.0 网站的创业思考[转]
    关于web3.0的标准:吃喝买卖随己
    左右均自适应高度
  • 原文地址:https://www.cnblogs.com/lyc94620/p/9598514.html
Copyright © 2011-2022 走看看