New file |
| | |
| | | <?php |
| | | |
| | | /** |
| | | * Redis 拓展类 |
| | | * @author: 喵了个咪 <wenzhenxi@vip.qq.com> 2015-11-15 |
| | | * |
| | | * @author: Axios <axioscros@aliyun.com> 2016-09-01 |
| | | * |
| | | * @update 2016-09-01 |
| | | * 1. 增加__call魔术方法,重载当前类中方法,统一切换DB,缩减代码行数,减少类中方法互相调用时,重复切换DB |
| | | * 2. 增加save_time方法,更新具有有效时间key的value,并且不重置有效时间,使用方式: DI()->redis->save_time($key, $value,$dbname); |
| | | * 3. 增加counter_forever方法,永久计数器,每次调用递增1,使用方式: DI()->redis->counter_forever($key,$dbname); |
| | | * 4. 增加counter_time_create方法,创建临时计数器,每次调用重置计数器和有效时间,使用方式: DI()->redis->counter_time_create($key,$expire,$dbname); |
| | | * 5. 增加counter_time_update方法,更新临时计数器,每次调用递增1,使用方式: DI()->redis->counter_time_update($key,$dbname); |
| | | * 6. 修复一处bug,get_time_ttl方法中,$this->unformatValue($value)修改为$value。修改前,调用此方法,会一直回调false |
| | | * |
| | | */ |
| | | class Redis_Lite extends PhalApi_Cache_Redis{ |
| | | |
| | | private $db_old; |
| | | |
| | | /** |
| | | * 重载方法,统一切换DB |
| | | * |
| | | * @param $name |
| | | * @param $arguments |
| | | * @return mixed |
| | | * |
| | | * @author: Axios <axioscros@aliyun.com> 2016-09-01 |
| | | */ |
| | | public function __call($name, $arguments) |
| | | { |
| | | $last = count($arguments)-1; |
| | | $dbname = $arguments[$last]; |
| | | $this->switchDB($dbname); |
| | | unset($arguments[$last]); |
| | | $arguments = empty($arguments)? array():$arguments; |
| | | return call_user_func_array(array($this,$name),$arguments); |
| | | } |
| | | |
| | | //---------------------------------------------------string类型------------------------------------------------- |
| | | /** |
| | | * 将value 的值赋值给key,生存时间为永久 并根据名称自动切换库 |
| | | */ |
| | | protected function set_forever($key, $value){ |
| | | return $this->redis->set($this->formatKey($key), $this->formatValue($value)); |
| | | } |
| | | |
| | | /** |
| | | * 获取value 并根据名称自动切换库 |
| | | */ |
| | | protected function get_forever($key){ |
| | | $value = $this->redis->get($this->formatKey($key)); |
| | | return $value !== FALSE ? $this->unformatValue($value) : NULL; |
| | | } |
| | | |
| | | /** |
| | | * 存入一个有实效性的键值队 |
| | | */ |
| | | protected function set_time($key, $value, $expire = 600){ |
| | | return $this->redis->setex($this->formatKey($key), $expire, $this->formatValue($value)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 更新具有有效时间key的value,不重置有效时间 |
| | | * @author Axios <axioscros@aliyun.com> |
| | | */ |
| | | protected function save_time($key, $value) |
| | | { |
| | | if($this->get_exists($key)){ |
| | | $ttl = $this->get_time_ttl($key); |
| | | return $this->set_time($key,$value,$ttl); |
| | | } |
| | | |
| | | return NULL; |
| | | } |
| | | |
| | | /** |
| | | * 统一get/set方法,对于set_Time使用get_Time |
| | | */ |
| | | protected function get_time($key){ |
| | | $value = $this->redis->get($this->formatKey($key)); |
| | | return $value !== FALSE ? $this->unformatValue($value) : NULL; |
| | | } |
| | | |
| | | /** |
| | | * 得到一个key的生存时间 |
| | | */ |
| | | protected function get_time_ttl($key){ |
| | | $value = $this->redis->ttl($this->formatKey($key)); |
| | | return $value !== FALSE ? $value : NULL; |
| | | } |
| | | |
| | | /** |
| | | * 批量插入k-v,请求的v需要是一个数组 如下格式 |
| | | * array('key0' => 'value0', 'key1' => 'value1') |
| | | */ |
| | | protected function set_list($value){ |
| | | $data = array(); |
| | | foreach($value as $k => $v){ |
| | | $data[$this->formatKey($k)] = $this->formatValue($v); |
| | | } |
| | | return $this->redis->mset($data); |
| | | } |
| | | |
| | | /** |
| | | * 批量获取k-v,请求的k需要是一个数组 |
| | | */ |
| | | protected function get_list($key){ |
| | | $data = array(); |
| | | foreach($key as $k => $v){ |
| | | $data[] = $this->formatKey($v); |
| | | } |
| | | $rs = $this->redis->mget($data); |
| | | foreach($rs as $k => $v){ |
| | | $rs[$k] = $this->unformatValue($v); |
| | | } |
| | | return $rs; |
| | | } |
| | | |
| | | /** |
| | | * 判断key是否存在。存在 true 不在 false |
| | | */ |
| | | protected function get_exists($key){ |
| | | return $this->redis->exists($this->formatKey($key)); |
| | | } |
| | | |
| | | /** |
| | | * 返回原来key中的值,并将value写入key |
| | | */ |
| | | protected function get_getSet($key, $value){ |
| | | $value = $this->redis->getSet($this->formatKey($key), $this->formatValue($value)); |
| | | return $value !== FALSE ? $this->unformatValue($value) : NULL; |
| | | } |
| | | |
| | | /** |
| | | * string,名称为key的string的值在后面加上value |
| | | */ |
| | | protected function set_append($key, $value){ |
| | | return $this->redis->append($this->formatKey($key), $this->formatValue($value)); |
| | | } |
| | | |
| | | /** |
| | | * 返回原来key中的值,并将value写入key |
| | | */ |
| | | protected function get_strlen($key){ |
| | | return $this->redis->strlen($this->formatKey($key)); |
| | | } |
| | | |
| | | /** |
| | | * 自动增长 |
| | | * value为自增长的值默认1 |
| | | */ |
| | | protected function get_incr($key, $value = 1){ |
| | | return $this->redis->incr($this->formatKey($key), $value); |
| | | } |
| | | |
| | | /** |
| | | * 自动减少 |
| | | * value为自减少的值默认1 |
| | | */ |
| | | protected function get_decr($key, $value = 1){ |
| | | return $this->redis->decr($this->formatKey($key), $value); |
| | | } |
| | | //------------------------------------------------List类型------------------------------------------------- |
| | | |
| | | /** |
| | | * 写入队列左边 并根据名称自动切换库 |
| | | */ |
| | | protected function set_lPush($key, $value){ |
| | | return $this->redis->lPush($this->formatKey($key), $this->formatValue($value)); |
| | | } |
| | | |
| | | /** |
| | | * 写入队列左边 如果value已经存在,则不添加 并根据名称自动切换库 |
| | | */ |
| | | protected function set_lPushx($key, $value){ |
| | | return $this->redis->lPushx($this->formatKey($key), $this->formatValue($value)); |
| | | } |
| | | |
| | | /** |
| | | * 写入队列右边 并根据名称自动切换库 |
| | | */ |
| | | protected function set_rPush($key, $value){ |
| | | return $this->redis->rPush($this->formatKey($key), $this->formatValue($value)); |
| | | } |
| | | |
| | | /** |
| | | * 写入队列右边 如果value已经存在,则不添加 并根据名称自动切换库 |
| | | */ |
| | | protected function set_rPushx($key, $value){ |
| | | return $this->redis->rPushx($this->formatKey($key), $this->formatValue($value)); |
| | | } |
| | | |
| | | /** |
| | | * 读取队列左边 |
| | | */ |
| | | protected function get_lPop($key){ |
| | | $value = $this->redis->lPop($this->formatKey($key)); |
| | | return $value != FALSE ? $this->unformatValue($value) : NULL; |
| | | } |
| | | |
| | | /** |
| | | * 读取队列右边 |
| | | */ |
| | | protected function get_rPop($key){ |
| | | $value = $this->redis->rPop($this->formatKey($key)); |
| | | return $value != FALSE ? $this->unformatValue($value) : NULL; |
| | | } |
| | | |
| | | /** |
| | | * 读取队列左边 如果没有读取到阻塞一定时间 并根据名称自动切换库 |
| | | */ |
| | | protected function get_blPop($key){ |
| | | $value = $this->redis->blPop($this->formatKey($key), DI()->config->get('app.redis.blocking')); |
| | | return $value != FALSE ? $this->unformatValue($value[1]) : NULL; |
| | | } |
| | | |
| | | /** |
| | | * 读取队列右边 如果没有读取到阻塞一定时间 并根据名称自动切换库 |
| | | */ |
| | | protected function get_brPop($key){ |
| | | $value = $this->redis->brPop($this->formatKey($key), DI()->config->get('app.redis.blocking')); |
| | | return $value != FALSE ? $this->unformatValue($value[1]) : NULL; |
| | | } |
| | | |
| | | /** |
| | | * 名称为key的list有多少个元素 |
| | | */ |
| | | protected function get_lSize($key){ |
| | | return $this->redis->lSize($this->formatKey($key)); |
| | | } |
| | | |
| | | /** |
| | | * 返回名称为key的list中指定位置的元素 |
| | | */ |
| | | protected function set_lSet($key, $index, $value){ |
| | | return $this->redis->lSet($this->formatKey($key), $index, $this->formatValue($value)); |
| | | } |
| | | |
| | | /** |
| | | * 返回名称为key的list中指定位置的元素 |
| | | */ |
| | | protected function get_lGet($key, $index){ |
| | | $value = $this->redis->lGet($this->formatKey($key), $index); |
| | | return $value != FALSE ? $this->unformatValue($value[1]) : NULL; |
| | | } |
| | | |
| | | /** |
| | | * 返回名称为key的list中start至end之间的元素(end为 -1 ,返回所有) |
| | | */ |
| | | protected function get_lRange($key, $start, $end){ |
| | | $rs = $this->redis->lRange($this->formatKey($key), $start, $end); |
| | | foreach($rs as $k => $v){ |
| | | $rs[$k] = $this->unformatValue($v); |
| | | } |
| | | return $rs; |
| | | } |
| | | |
| | | /** |
| | | * 截取名称为key的list,保留start至end之间的元素 |
| | | */ |
| | | protected function get_lTrim($key, $start, $end){ |
| | | $rs = $this->redis->lTrim($this->formatKey($key), $start, $end); |
| | | foreach($rs as $k => $v){ |
| | | $rs[$k] = $this->unformatValue($v); |
| | | } |
| | | return $rs; |
| | | } |
| | | |
| | | //未实现 lRem lInsert rpoplpush |
| | | |
| | | //----------------------------------------------------set类型--------------------------------------------------- |
| | | //----------------------------------------------------zset类型--------------------------------------------------- |
| | | //----------------------------------------------------Hash类型--------------------------------------------------- |
| | | |
| | | //----------------------------------------------------通用方法--------------------------------------------------- |
| | | /** |
| | | * 永久计数器,回调当前计数 |
| | | * @author Axios <axioscros@aliyun.com> |
| | | */ |
| | | public function counter_forever($key,$dbname=0){ |
| | | $this->switchDB($dbname); |
| | | if($this->get_exists($key)){ |
| | | $count = $this->get_forever($key); |
| | | $count++; |
| | | $this->set_forever($key,$count); |
| | | }else{ |
| | | $count = 1; |
| | | $this->set_forever($key,$count); |
| | | } |
| | | |
| | | return $count; |
| | | } |
| | | /** |
| | | * 创建具有有效时间的计数器,回调当前计数,单位毫秒ms |
| | | * @author Axios <axioscros@aliyun.com> |
| | | */ |
| | | public function counter_time_create($key,$expire = 1000,$dbname=0){ |
| | | $this->switchDB($dbname); |
| | | $count = 1; |
| | | $this->set_time($key,$count,$expire); |
| | | $this->redis->pSetEx($this->formatKey($key), $expire, $this->formatValue($count)); |
| | | return $count; |
| | | } |
| | | /** |
| | | * 更新具有有效时间的计数器,回调当前计数 |
| | | * @author Axios <axioscros@aliyun.com> |
| | | */ |
| | | public function counter_time_update($key,$dbname=0){ |
| | | $this->switchDB($dbname); |
| | | if($this->get_exists($key)){ |
| | | $count = $this->get_time($key); |
| | | $count++; |
| | | $expire = $this->redis->pttl($this->formatKey($key)); |
| | | $this->set_time($key,$count,$expire); |
| | | return $count; |
| | | } |
| | | return false; |
| | | } |
| | | /** |
| | | * 设定一个key的活动时间(s) |
| | | */ |
| | | protected function setTimeout($key, $time = 600){ |
| | | return $this->redis->setTimeout($key, $time); |
| | | } |
| | | |
| | | /** |
| | | * 返回key的类型值 |
| | | */ |
| | | protected function type($key){ |
| | | return $this->redis->type($key); |
| | | } |
| | | |
| | | /** |
| | | * key存活到一个unix时间戳时间 |
| | | */ |
| | | protected function expireAt($key, $time = 600){ |
| | | return $this->redis->expireAt($key, $time); |
| | | } |
| | | |
| | | /** |
| | | * 随机返回key空间的一个key |
| | | */ |
| | | public function randomKey(){ |
| | | return $this->redis->randomKey(); |
| | | } |
| | | |
| | | /** |
| | | * 返回满足给定pattern的所有key |
| | | */ |
| | | protected function keys($key, $pattern){ |
| | | return $this->redis->keys($key, $pattern); |
| | | } |
| | | |
| | | /** |
| | | * 查看现在数据库有多少key |
| | | */ |
| | | protected function dbSize(){ |
| | | return $this->redis->dbSize(); |
| | | } |
| | | |
| | | /** |
| | | * 转移一个key到另外一个数据库 |
| | | */ |
| | | protected function move($key, $db){ |
| | | $arr = DI()->config->get('app.redis.DB'); |
| | | $rs = isset($arr[$db]) ? $arr[$db] : $db; |
| | | return $this->redis->move($key, $rs); |
| | | } |
| | | |
| | | /** |
| | | * 给key重命名 |
| | | */ |
| | | protected function rename($key, $key2){ |
| | | |
| | | return $this->redis->rename($key, $key2); |
| | | } |
| | | |
| | | /** |
| | | * 给key重命名 如果重新命名的名字已经存在,不会替换成功 |
| | | */ |
| | | protected function renameNx($key, $key2){ |
| | | return $this->redis->renameNx($key, $key2); |
| | | } |
| | | |
| | | /** |
| | | * 删除键值 并根据名称自动切换库(对所有通用) |
| | | */ |
| | | protected function del($key){ |
| | | return $this->redis->del($this->formatKey($key)); |
| | | } |
| | | |
| | | /** |
| | | * 返回redis的版本信息等详情 |
| | | */ |
| | | public function info(){ |
| | | return $this->redis->info(); |
| | | } |
| | | |
| | | /** |
| | | * 切换DB并且获得操作实例 |
| | | */ |
| | | public function get_redis(){ |
| | | return $this->redis; |
| | | } |
| | | |
| | | /** |
| | | * 查看连接状态 |
| | | */ |
| | | public function ping(){ |
| | | return $this->redis->ping(); |
| | | } |
| | | |
| | | /** |
| | | * 内部切换Redis-DB 如果已经在某个DB上则不再切换 |
| | | */ |
| | | protected function switchDB($name){ |
| | | $arr = DI()->config->get('app.redis.DB'); |
| | | if(is_int($name)){ |
| | | $db = $name; |
| | | }else{ |
| | | $db = isset($arr[$name]) ? $arr[$name] : 0; |
| | | } |
| | | if($this->db_old != $db){ |
| | | $this->redis->select($db); |
| | | $this->db_old = $db; |
| | | } |
| | | } |
| | | //-------------------------------------------------------谨慎使用------------------------------------------------ |
| | | |
| | | /** |
| | | * 清空当前数据库 |
| | | */ |
| | | protected function flushDB(){ |
| | | return $this->redis->flushDB(); |
| | | } |
| | | |
| | | /** |
| | | * 清空所有数据库 |
| | | */ |
| | | public function flushAll(){ |
| | | return $this->redis->flushAll(); |
| | | } |
| | | |
| | | /** |
| | | * 选择从服务器 |
| | | */ |
| | | public function slaveof($host, $port){ |
| | | return $this->redis->slaveof($host, $port); |
| | | } |
| | | |
| | | /** |
| | | * 将数据同步保存到磁盘 |
| | | */ |
| | | public function save(){ |
| | | return $this->redis->save(); |
| | | } |
| | | |
| | | /** |
| | | * 将数据异步保存到磁盘 |
| | | */ |
| | | public function bgsave(){ |
| | | return $this->redis->bgsave(); |
| | | } |
| | | |
| | | /** |
| | | * 返回上次成功将数据保存到磁盘的Unix时戳 |
| | | */ |
| | | public function lastSave(){ |
| | | return $this->redis->lastSave(); |
| | | } |
| | | |
| | | /** |
| | | * 使用aof来进行数据库持久化 |
| | | */ |
| | | protected function bgrewriteaof(){ |
| | | return $this->redis->bgrewriteaof(); |
| | | } |
| | | } |