1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315 |
- <?php
- namespace loyalsoft;
- define('Redis_Debug', true); // 调试redis操作
- //require __DIR__ . '/Predis/Autoloader.php';
- require __DIR__ . '/predis-2.0.0/src/Autoloader.php'; # 2022.8.16 更新Predis代码到2.0
- \Predis\Autoloader::register();
- /**
- * redis操作封装,
- * 关于阿里云redis的支持命令和未开放命令见:
- * https://docs.aliyun.com/?spm=5176.7630237.9.3.WfKF0A#/pub/kvstore/quick-start/kvstore-redis-command
- * 腾讯云支持的命令:
- * https://www.qcloud.com/doc/product/239/%E4%BD%BF%E7%94%A8%E9%99%90%E5%88%B6
- * redis相关命令说明见:http://redisdoc.com/
- *
- * 支持命令集接口见: /phpRedisAdmin/predis/src/ClientInterface.php
- * @version <br/>
- * 1.0.4 取消公共基类CMemBase,后面可能不太会用到memcache(d)了. gwang 2020年11月23日
- * 1.0.3 扩展list相关api的操作方法, 针对values统一做json编解码处理.
- * 整理其他数据结构的操作方法, normal/hash/list api内部做json编解码处理,
- * set/zset value 默认不做json编解码处理, 针对set/zset的value,不推荐写入太大或复杂的数据.
- * gwang 2017年4月28日 <br/>
- * 1.0.2 扩充特有数据结构的操作方法, gwang 2016.4.21 <br/>
- * 1.0.1 扩充了事务的使用方法.开发竞争类业务,圣树争夺战, gwang 2016.3.21 <br/>
- * 1.0.0 pguan,基础功能, 方法与memcache看齐. <br/>
- */
- class CRedisUtil {
- // public $keyDic = null;
- // <editor-fold defaultstate="collapsed" desc="性能分析">
- static $caller_counter = array();
- /**
- * 调用统计
- */
- public static function AddCallCount() {
- self::$caller_counter[] = DebugHelper::get_call_stack(3, 2, true);
- }
- // </editor-fold>
- /**
- *
- * @var ClientInterface
- */
- public $redis = null;
- /**
- * 自动回收
- */
- function __destruct() {
- $this->close();
- }
- private static function debug() {
- if (defined('Redis_Debug') && Redis_Debug) {
- // DebugHelper::debug(DebugHelper::get_call_stack());
- self::AddCallCount();
- }
- }
- // <editor-fold defaultstate="collapsed" desc=" 实现CMemBase操作接口">
- /**
- * 添加一个值
- * @param string $key
- * @param string $value
- * @param int $ts=0 此值无效
- * @return true 成功, false 失败,此key已经存在
- */
- public function add($key, $value, $ts = 0) {
- self::debug();
- return $this->setnx($key, JsonUtil::encode($value));
- }
- /**
- * 复制一个变量到另一个key
- * @param string $surKey 源数据的key
- * @param string $desKey 目的数据的key
- */
- public function copy($surKey, $desKey) {
- self::debug();
- return $this->set($desKey, $this->get($surKey));
- }
- /**
- * 一次取多个值
- * @param array(string) $keys
- * @return array
- */
- public function getMulti($keys) {
- self::debug();
- // var_dump($keys);
- return $this->mget($keys);
- }
- /**
- * 设置多个值
- * @param dic $dict [{"key":value},{"key":value},....]
- * @return true 永远成功
- */
- public function setMutlti($dict) {
- self::debug();
- $params = array();
- foreach ($dict as $key => $val) {
- $params[$key] = is_string($val) ? $val : JsonUtil::encode($val);
- }
- if (count($params) <= 0) {
- return TRUE;
- }
- $this->mset($params);
- return true;
- }
- /**
- * 替换某个值
- * @param string $key
- * @param string $value
- * @param int $ts
- * @return boolean true 成功,false 失败
- */
- public function replace($key, $value, $ts = 0) {
- self::debug();
- $ret = $this->redis->setex($key, $value, $ts);
- if (strtolower($ret) == "ok") {
- return true;
- }
- $this->logErr("replace" . $ret);
- return false;
- }
- /**
- * 不经过jsonencode直接存储
- * @deprecated since version 20160413113950 经过自己考察json_encode对数据的影响并不存在
- * @param type $key
- * @return any
- */
- public function getWithoutJson($key) {
- self::debug();
- return $this->redis->get($key);
- }
- /**
- * 不经过jsondecode直接返回
- * @deprecated since version 20160413113950 经过自己考察json_encode对数据的影响并不存在
- * @param string $key
- * @param string $value
- * @param int $ts
- * @return boolean
- */
- public function setWithoutJson($key, $value, $ts = 0) {
- self::debug();
- $ret = $this->redis->set($key, $value, $ts);
- if (strtolower($ret) == "ok") {
- return true;
- }
- $this->logErr("set" . $ret);
- return false;
- }
- /**
- * 输出日志
- * @param mixed $msg
- */
- private function logErr($msg) {
- CLog::err($msg, "Redis Err:");
- }
- /**
- * 连接
- * @param string $host
- * @param string $port
- * @param string $pwd
- * @param string $db 数据库, 不建议输入参数, 如果是购买云实例只有一个db.
- * @return \CRedisUtil
- */
- public function conn($host, $port, $pwd = "", $db = 0) {
- // DebugHelper::print_stack_trace();
- // $this->redis = new \Predis\Client(array(
- // $this->redis = new \Redis();
- // $this->redis->connect('127.0.0.1', 6379);
- // $this->redis->auth($pwd);
- $this->redis = new \Predis\Client(array(
- 'scheme' => 'tcp',
- 'host' => $host,
- 'port' => $port,
- 'password' => $pwd,
- ));
- if ($db != 0) {
- $this->redis->select($db);
- }
- // $this->keyDic = new \stdClass();
- return $this;
- }
- /**
- * 关闭连接
- */
- public function close() {
- $this->redis->quit();
- }
- /**
- * 获取指定键值
- * @param string $key
- * @return any json_decode($result)
- */
- public function get($key) {
- self::debug();
- $result = $this->redis->get($key);
- if (!$result || $result == "" || $result == null) {
- return null;
- }
- // $this->keyDic->$key = $result;
- return JsonUtil::decode($result);
- }
- /**
- * 将字符串值 $val 关联到 key
- * @param string $key
- * @param any $value
- * @param int $ts default(0) 过期时间(单位秒)
- * @return boolean 成功true,失败false
- */
- public function set($key, $value, $ts = 0) {
- self::debug();
- if ($value === null || $value === "") { # 这里必须用全等符号
- return false;
- }
- if (is_string($value)) { # 使用json序列化后存储
- $val = $value;
- } else {
- $val = JsonUtil::encode($value);
- }
- if ($ts > 0) { # 将会设置TTL 到期删除 ps: replaced by gwang 增加过期时间
- $ret = $this->redis->setex($key, $ts, $val);
- } else { # 0:永不过期,如果原来有TTL将会清除TTL.
- $ret = $this->redis->set($key, $val);
- }
- if ("OK" != $ret) {
- $this->logErr("Set:" . $ret);
- return false;
- }
- return true;
- }
- /**
- * 安全的写入操作
- * @deprecated since version 1.0 云平台暂时不支持
- * @param string $key
- * @param any $value
- * @return boolean 成功true,失败false
- */
- public function cas($key, $value, $ts = 0) {
- if (false) { # ps. 各云平台皆不支持eval方法执行lua脚本.等开放支持的时候才是真正支持cas的时候
- $castoken = $this->keyDic->$key;
- # # 定义一段脚本
- $script = <<<casscript
- if redis.call("get",KEYS[1]) == "$castoken"
- then
- return redis.call("set",KEYS[1],ARGV[1])
- else
- return 0
- end
- casscript;
- $ret = $this->redis->eval($script, 1, $key, $value); # redis 执行lua脚本
- if (0 == $ret) {
- return false;
- }
- return true;
- }
- // 非线程安全,原因见下
- return $this->set($key, $value, $ts);
- }
- /**
- * 删除一个指定键值
- * @param string $key
- * @return int 删除键的个数
- */
- public function delete($key) {
- self::debug();
- my_Assert(is_string($key), "arg key should be a string!");
- $infos = array();
- array_push($infos, $key);
- return $this->redis->del($infos);
- }
- /**
- * 删除一个或多个指定键值
- * @param array $keys
- * @return int 删除键的个数
- */
- public function deleteMulti($keys) {
- self::debug();
- $infos = (array) $keys; # 强制转数据类型为数组
- return $this->redis->del($infos);
- }
- // </editor-fold>
- //
- // <editor-fold defaultstate="collapsed" desc=" normal 普通对象操作 mget/mset">
- /**
- * 返回所有(一个或多个)给定 key 的值
- * 如果给定的 key 里面,有某个 key 不存在,那么这个 key 返回特殊值 nil 。因此,该命令永不失败。
- * @param array $keys
- * @return array 一个包含所有给定 key 的值的列表
- */
- private function mget($keys) {
- // self::debug();
- $ret = array();
- if (count($keys)) {
- $ctx = $this->redis->mget($keys);
- $mval = count($ctx);
- for ($i = 0;
- $i < $mval;
- $i++) {
- $ret[] = JsonUtil::decode($ctx[$i]);
- }
- }
- return $ret;
- }
- /**
- * Add函数拥有相同效果 \n
- * 将 key 的值设为 value ,当且仅当 key 不存在。
- * 若给定的 key 已经存在,则不做任何动作。
- * @param type $key
- * @param type $val
- * @return boolean 成功true,失败false
- */
- private function setnx($key, $val) {
- self::debug();
- $ret = $this->redis->setnx($key, $val);
- // 成功返回1, 失败返回0
- if (1 == $ret) {
- return true;
- } else {
- $this->logErr("setnx:" . $ret . "(值已存在)");
- }
- return false;
- }
- /**
- * 同时设置一个或多个 key-value 对
- * 如果某个给定 key 已经存在,那么 MSET 会用新值覆盖原来的旧值
- * @param array $dict
- * @return mixed
- */
- private function mset($dict) {
- self::debug();
- return $this->redis->mset($dict);
- }
- /**
- * 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在
- * 即使只有一个给定 key 已存在, MSETNX 也会拒绝执行所有给定 key 的设置操作
- *
- * @param array $dict
- * @return int
- */
- public function msetnx($dict) {
- self::debug();
- $ret = $this->redis->msetnx($dict);
- return $ret == 1;
- }
- /**
- * 检测指定键值是否存在
- * @param type $key
- * @return boolean true 存在, false 不存在
- */
- public function exists($key) {
- self::debug();
- return $this->redis->exists($key) == 1;
- }
- /**
- * 将 key 中储存的数字值增一
- * 如果 key 不存在,那么 key 的值会先被初始化为 0
- * 如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误
- * 本操作的值限制在 64 位(bit)有符号数字表示之内
- * @param type $key
- * @return int 执行 INCR 命令之后 key 的值
- */
- public function increment($key) {
- self::debug();
- return $this->redis->incr($key);
- }
- /**
- * 将 key 中储存的数字值增加 一个int值
- * 如果 key 不存在,那么 key 的值会先被初始化为 0
- * 如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误
- * 本操作的值限制在 64 位(bit)有符号数字表示之内
- * @param string $key
- * @param int $i 增加的值
- * @return int 执行 INCR 命令之后 key 的值
- */
- public function incrby($key, $i) {
- self::debug();
- return $this->redis->incrby($key, $i);
- }
- // </editor-fold>
- //
- //======================== 以下部分 added by gwang at 2016-4-14 15:17:25 =================
- // <editor-fold defaultstate="collapsed" desc=" 辅助函数 ">
- /**
- * Server功能,看服务器是否连通
- * @return boolean true连通正常
- */
- public function ping() {
- $ret = $this->redis->ping();
- if ($ret == "PONG") {
- return true;
- }
- $this->logErr("ping:" . $ret);
- return false;
- }
- /**
- * 对数组进行json编码
- * @param array $values
- * @return array
- */
- static private function json_encode_arr($values) {
- $arr = array();
- if (is_array($values)) {
- $arr = array_map(function ($v) {
- return JsonUtil::encode($v);
- }, $values);
- } else {
- $arr[] = JsonUtil::encode($values);
- }
- return $arr;
- }
- /**
- * 对数组进行json解码
- * @param array $values
- * @return array
- */
- static private function json_decode_arr(array $values) {
- $arr = array();
- if (is_array($values)) {
- $arr = array_map(function ($v) {
- return JsonUtil::decode($v);
- }, $values);
- } else {
- $arr[] = JsonUtil::decode($values);
- }
- return $arr;
- }
- // </editor-fold>
- //
- // <editor-fold defaultstate="collapsed" desc=" 事务操作 ">
- /**
- * 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
- * @param string $key
- */
- public function watch($key) {
- $this->redis->watch($key);
- }
- /**
- * 取消监视
- */
- public function unwatch() {
- $this->redis->unwatch();
- }
- /**
- * 开启事务
- */
- public function multi() {
- $this->redis->multi();
- }
- /**
- * 执行事务
- * @return type 事务块内所有命令的返回值,按命令执行的先后顺序排列。当操作被打断时,返回空值 nil 。
- */
- public function exec() {
- return $this->redis->exec();
- }
- // </editor-fold>
- //
- // == ↓ 下面是Redis独有的数据类型操作 ↓ ==
- //
- // <editor-fold defaultstate="collapsed" desc=" set 集合操作 ">
- /**
- * 集合(set) - 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。
- * 集合不存在时将会创建集合
- * @param string $key
- * @param string[] $members (mixed is ok, i will transmit it.)
- * @return int
- * @expectedException type not set error
- */
- public function sadd($key, $members) {
- self::debug();
- if (!is_array($members)) { # 防御: 参数不为数组
- if (!is_string($members)) { # 防御: 参数不为字符串
- $members = JsonUtil::encode($members);
- }
- $members = array($members); # 转为字符串数组
- }
- return $this->redis->sadd($key, $members);
- }
- /**
- * 集合(set) - 将一个或多个 member 元素从集合 key 当中移除
- * 集合不存在时将会创建集合
- * @param string $key
- * @param string[] $members
- * @return int
- * @expectedException type not set error
- */
- public function sremove($key, $members) {
- self::debug();
- return $this->redis->srem($key, $members);
- }
- /**
- * 集合(set) - 返回集合 key 的基数(集合中元素的数量)。
- * @param strig $key
- * @return int
- */
- public function scard($key) {
- self::debug();
- return $this->redis->scard($key);
- }
- /**
- * 集合(set) - 等效于scard: 返回集合 key 的基数(集合中元素的数量)。
- * @param string $key
- * @return int
- *
- */
- public function slen($key) {
- self::debug();
- return $this->scard($key);
- }
- /**
- * 集合(set) - 判断某个元素是否属于集合
- * @param string $key
- * @param string $member
- * @return bool
- */
- public function sismember($key, $member) {
- self::debug();
- return $this->redis->sismember($key, $member) == 1;
- }
- /**
- * 集合(set) - 返回集合 key 中的所有成员。
- * @param type $key
- * @return array 不存在的key视为空集合
- */
- public function smembers($key) {
- self::debug();
- return $this->redis->smembers($key);
- }
- /**
- * 集合(set) - 如果命令执行时,只提供了 key 参数,那么返回集合中的10个随机元素。
- * 如果 count 为正数,且小于集合基数,那么命令返回一个包含 count 个元素的数组,数组中的元素各不相同。如果 count 大于等于集合基数,那么返回整个集合。
- * 如果 count 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值。
- * @param string $key
- * @param int $count =10
- * @return array
- */
- public function srandmember($key, $count = 10) {
- self::debug();
- return $this->redis->srandmember($key, $count);
- }
- // </editor-fold>
- //
- // <editor-fold defaultstate="collapsed" desc=" hash 哈希表操作 ">
- /**
- * 哈希表 - 删除 字段
- * @param string $key
- * @param array $fields
- * @return int 删除的字段的数量
- */
- public function hdel($key, $fields) {
- self::debug();
- return $this->redis->hdel($key, $fields);
- }
- /**
- * 哈希表 - 判断field是否存在
- * @param string $key
- * @param string $field
- * @return boolean true=存在,false 找不到
- */
- public function hexists($key, $field) {
- self::debug();
- return $this->redis->hexists($key, $field) == 1;
- }
- /**
- * 哈希表 - 获取字段
- * @param string $key
- * @param string $field 字段名
- * @return mixed json_decoded object
- */
- public function hget($key, $field) {
- self::debug();
- $ret = $this->redis->hget($key, $field);
- return JsonUtil::decode($ret);
- }
- /**
- * 哈希表 - 获取所有字段
- * @param string $key
- * @return stdclass/associate_array (适用箭头取变量写法)
- */
- public function hgetall($key) {
- self::debug();
- $ret = ArrayInit();
- $arr = $this->redis->hgetall($key);
- foreach ($arr as $k => $v) {
- $ret[$k] = JsonUtil::decode($v);
- }
- // 转为关联数组({})再返回, 方便代码中使用箭头写法
- return JsonUtil::decode(JsonUtil::encode($ret));
- }
- /**
- * 哈希表 - 获取表中字段数量
- * @param string $key
- * @return int
- */
- public function hlen($key) {
- self::debug();
- return $this->redis->hlen($key);
- }
- /**
- * 哈希表 - 同时获取多个字段
- * @param string $key
- * @param array $fields
- * @return Array
- */
- public function hmget($key, $fields) {
- self::debug();
- $ret = ArrayInit();
- if (is_array($fields) && count($fields) > 0) {
- $arr = $this->redis->hmget($key, $fields);
- foreach ($arr as $k => $v) {
- $ret[$k] = JsonUtil::decode($v);
- }
- }
- // 转为关联数组({})再返回, 方便代码中使用箭头写法
- return JsonUtil::decode(JsonUtil::encode($ret));
- }
- /**
- * 哈希表 - 同时设置多个字段的值
- * @param string $key
- * @param assoc_array $dictionary
- * @return boolean true成功
- */
- public function hmset($key, $dictionary) {
- self::debug();
- $newdic = ArrayInit();
- foreach ($dictionary as $k => $v) {
- $newdic[$k] = JsonUtil::encode($v);
- }
- $ret = $this->redis->hmset($key, $newdic);
- if (strtolower($ret) == 'ok') {
- return true;
- }
- return false;
- }
- /**
- * 哈希表 - 同时设置多个字段的值(带Not Changed校验)
- * @param string $key
- * @param HashSaver $dic (要包含$stVer字段用以校验)
- * @return boolean 写入是否成功
- */
- public function hmset_Cas(string $key, HashSaver $dic) {
- # # 定义一段脚本
- static $script = <<<Lua
- local key,casToken,casVer, dic = KEYS[1], KEYS[2], ARGV[1], ARGV[2]
- local cv = redis.call("hget", key, casToken)
- local t = cjson.decode( dic )
- if not cv or tonumber(cv) < tonumber(casVer) then
- for k, v in pairs(t) do
- if type(v) =="table" then -- 加戏,如果value是对象的话, 继续encode一下.
- v=cjson.encode(v)
- end
- redis.call("hset", key, k, v)
- end
- return 1
- else
- return 0
- end
- Lua;
- try {
- $castoken = "stVer";
- $casVer = $dic->stVer;
- // CLog::err($dic->toString());
- // var_dump($dic->toString());
- $ret = $this->redis->eval($script, 2, $key, $castoken, $casVer, $dic->toString()); # redis 执行lua脚本
- // CLog::err($dic->toString());
- if (0 == $ret) {
- return false;
- }
- } catch (\Exception $e) {
- CLog::err($e->getMessage());
- return false;
- }
- return true;
- }
- /**
- * 哈希表 - 设置或新建一个字段的值
- * @param string $key
- * @param string $field
- * @param $mixed $value
- * @return int 0 覆盖旧值, 1 新建字段
- */
- public function hset($key, $field, $value) {
- self::debug();
- return $this->redis->hset($key, $field, JsonUtil::encode($value));
- }
- /**
- * 哈希表 - 增加一个新的field,已经存在则放弃操作返回false
- * @param string $key
- * @param string $field
- * @param string $value
- * @return boolean true成功
- */
- public function hsetnx($key, $field, $value) {
- self::debug();
- return $this->redis->hsetnx($key, $field, JsonUtil::encode($value)) == 1;
- }
- /**
- * 哈希表 - 按字段赠加 int值
- * @param string $key
- * @param string $field
- * @param int $increment
- * @return int
- */
- public function hincrby($key, $field, $increment) {
- self::debug();
- return $this->redis->hincrby($key, $field, $increment);
- }
- /**
- * 哈希表 - 按字段增加 float值
- * @param string $key
- * @param string $field
- * @param string $increment float值用string
- * @return string 用string存float值
- */
- public function hincrbyfloat($key, $field, $increment) {
- self::debug();
- return $this->redis->hincrbyfloat($key, $field, $increment);
- }
- /**
- * @param string $key
- * @return array
- */
- public function hkeys($key) {
- self::debug();
- return $this->redis->hkeys($key);
- }
- // * @method array hscan($key, $cursor, array $options = null)
- // * @method array hvals($key)
- // </editor-fold>
- //
- // <editor-fold defaultstate="collapsed" desc=" list 链表操作 ">
- //
- // <editor-fold defaultstate="collapsed" desc=" 阻塞的链表操作 ">
- /**
- * 链表 - 阻塞弹出, 当列表中没有元素的时候,命令会阻塞,直到等待超时或者有元素被添加到列表中.
- * @param array $keys 可以指定多个数组
- * @param int $timeout
- * @return array
- */
- public function blpop(array $keys, $timeout) {
- self::debug();
- $arr = $this->redis->blpop($keys, $timeout);
- $arr[1] = JsonUtil::decode($arr[1]); // 对value进行解包
- return $arr;
- }
- /**
- * 链表 - 阻塞队尾弹出, 当列表中没有元素的时候,命令会阻塞,直到等待超时或者有元素被添加到列表中.
- * @return array
- */
- public function brpop(array $keys, $timeout) {
- self::debug();
- $arr = $this->redis->brpop($keys, $timeout);
- $arr[1] = JsonUtil::decode($arr[1]);
- return $arr;
- }
- /**
- * 链表 - 阻塞版的 队尾弹出插入到队首. 本操作是原子的.
- *
- * @return array 假如在指定时间内没有任何元素被弹出,则返回一个 nil 和等待时长。
- * 反之,返回一个含有两个元素的列表,第一个元素是被弹出元素的值,第二个元素是等待时长。
- */
- public function brpoplpush($source, $destination, $timeout) {
- self::debug();
- $arr = $this->redis > brpoplpush($source, $destination, $timeout);
- $arr[0] = JsonUtil::decode($arr[0]);
- return $arr;
- }
- // </editor-fold>
- //
- /**
- * 链表 - 返回下标为index的元素
- * @return string
- */
- public function lindex($key, $index) {
- self::debug();
- $a = $this->redis->lindex($key, $index);
- return JsonUtil::decode($a);
- }
- /**
- * 链表 - 返回 链表key的长度
- * @return int
- * @param type $key
- */
- public function llen($key) {
- self::debug();
- return $this->redis->llen($key);
- }
- /**
- * 链表 - 移除并返回链表的队首元素.
- * @return string
- * @param type $key
- */
- public function lpop($key) {
- self::debug();
- $a = $this->redis->lpop($key);
- return JsonUtil::decode($a);
- }
- /**
- * 链表 - 向链表插入一个或多个值,链表不存在时创建链表并插入元素
- * @return int key存在却不是链表类型时返回一个错误.
- * @param type $key
- * @param array $values
- */
- public function lpush($key, $values) {
- self::debug();
- $arr = self::json_encode_arr($values);
- return $this->redis->lpush($key, $arr);
- }
- /**
- * 链表 - 取链表中指定下标区间的元素
- * @return array
- * @param string $key
- * @param int $start
- * @param int $stop
- */
- public function lrange($key, $start, $stop) {
- self::debug();
- $values = $this->redis->lrange($key, $start, $stop);
- return self::json_decode_arr($values);
- }
- /**
- * 链表 - 移除链表中 count 个值为 value的元素.
- * @return int
- * @param string $key
- * @param int $count
- * @param string $value
- */
- public function lrem($key, $count, $value) {
- self::debug();
- return $this->redis->lrem($key, $count, JsonUtil::encode($value));
- }
- /**
- * 链表 - 将链表中下标为index的 元素设置为value
- * @return mixed
- *
- * @param type $key
- * @param type $index
- * @param type $value
- */
- public function lset($key, $index, $value) {
- self::debug();
- return $this->redis->lset($key, $index, JsonUtil::encode($value));
- }
- /**
- * 链表 - 对链表进行修剪, 让链表只保留指定下标区间的元素,其余元素删除
- * @return bool true 成功, false 失败
- * @param string $key
- * @param int $start
- * @param int $stop
- */
- public function ltrim($key, $start, $stop) {
- self::debug();
- // return mixed: ok or fails
- $ret = $this->redis->ltrim($key, $start, $stop);
- if (strtolower($ret) == 'ok') {
- return true;
- }
- return false;
- }
- /**
- * 链表 - 从链表右侧(尾部)弹出一个元素,并返回该元素
- * @param string $key
- * @return string 列表的尾元素。当 key 不存在时,返回 nil
- */
- public function rpop($key) {
- self::debug();
- return JsonUtil::decode($this->redis->rpop($key));
- }
- /**
- * 将一个或多个值 value 插入到列表 key 的表尾(最右边)。
- * @param string $key
- * @param array $values
- * @return int
- */
- public function rpush($key, array $values) {
- self::debug();
- $arr = self::json_encode_arr($values);
- return $this->redis->rpush($key, $arr);
- }
- //
- // /**
- // * 链表 - 向链表中插入一个或多个值,链表不存在时,什么也不做.
- // * @return int
- // * @param type $key
- // * @param type $value
- // */
- // public function lpushx($key, $value)
- // {
- // return $this->redis->lpushx($key, $value);
- // }
- // /**
- // * 链表 - 将值 value 插入到链表 key 中 , 位于pivot之前或之后
- // * @return int -1:未找到pivot, 0:链表为空或者不存在.
- // *
- // * @param string $key 链表名称
- // * @param string $whence after/before pivot之前或之后
- // * @param string $pivot 插入pivot之前或之后
- // * @param string $value 要插入的value
- // */
- // public function linsert($key, $whence, $pivot, $value)
- // {
- // $this->redis->linsert($key, $whence, $pivot, $value);
- // }
- // /**
- // * 在一个原子时间内,执行以下两个动作
- // * 将列表 source 中的最后一个元素(尾元素)弹出,并返回给客户端。
- // * 将 source 弹出的元素插入到列表 destination ,作为 destination 列表的的头元素.
- // * @return string
- // */
- // public function rpoplpush($source, $destination)
- // {
- // throw new Exception("un implemented now!");
- // }
- // /**
- // * 将值 value 插入到列表 key 的表尾,当且仅当 key 存在并且是一个列表。
- // * 和 RPUSH 命令相反,当 key 不存在时, RPUSHX 命令什么也不做。
- // * @param type $key
- // * @param type $value
- // * @return int
- // */
- // public function rpushx($key, $value)
- // {
- // throw new Exception("un implemented now!");
- // }
- // </editor-fold>
- //
- // <editor-fold defaultstate="collapsed" desc=" zset 有序集合 ">
- /**
- * 有序集合 - 添加或更新元素 对于zset类型不建议写入太长, 太复杂的value
- * @param string $key
- * @param array $membersAndScoresDictionary array( 'value'=>score,'value'=>score,...), score可以是int或float
- * @return int 新增元素数量,不包含更新的元素
- */
- public function zadd($key, $membersAndScoresDictionary) {
- self::debug();
- return $this->redis->zadd($key, $membersAndScoresDictionary);
- }
- /**
- * 有序集合 - 给某个元素增加积分
- * @param string $key
- * @param string $member
- * @param int $increment
- * @return string
- */
- public function zincrby($key, $member, $increment = 1) {
- self::debug();
- return $this->redis->zincrby($key, $increment, $member);
- }
- /**
- * 有序集合 - 元素数量
- * @param string $key
- * @return int
- */
- public function zlen($key) {
- self::debug();
- return $this->redis->zcard($key);
- }
- /**
- * 有序集合 - 统计某区间元素数量
- * @param string $key
- * @param int/float $min 最低分
- * @param int/float $max 最高分
- * @return int
- */
- public function zcount($key, $min, $max) {
- self::debug();
- return $this->redis->zcount($key, $min, $max);
- }
- /**
- * 有序集合 - 获取集合指定区间内的成员, 第一个成员从0开始
- * @param string $key
- * @param int $start
- * @param int $stop Ps.以 -1 表示最后一个成员, -2 表示倒数第二个成员
- * @param boolean $withScore 返回值中是否带score字段
- * @return array (index=>member) or assoc_array (member=>score)
- */
- public function zrange($key, $start, $stop, $withScore = false) {
- self::debug();
- if ($withScore) {
- return $this->redis->zrange($key, $start, $stop, 'WITHSCORES');
- } else {
- return $this->redis->zrange($key, $start, $stop);
- }
- if ($withScore) {
- $ret = $this->redis->zrange($key, $start, $stop, 'WITHSCORES');
- DebugHelper::var_dump($ret);
- $ma = count($ret);
- $arr = array();
- for ($i = 0; $i < $ma; $i += 2) {
- $arr[$ret[$i]] = $ret[$i + 1];
- }
- return $arr;
- } else {
- $ret = $this->redis->zrange($key, $start, $stop);
- DebugHelper::var_dump($ret);
- return $ret;
- }
- }
- /**
- *
- * 有序集合 - 获取集合倒序之后,指定区间内的成员, 第一个成员从0开始
- * @param string $key
- * @param int $start
- * @param int $stop Ps.以 -1 表示最后一个成员, -2 表示倒数第二个成员
- * @param boolean $withScore 返回值中是否带score字段 default(false)
- * @return array (index=>member) or assoc_array (member=>score) 用foreach(=>)取
- */
- public function zrevrange($key, $start, $stop, $withScore = false) {
- self::debug();
- if ($withScore) {
- $r = $this->redis->zrevrange($key, $start, $stop, 'WITHSCORES');
- return $r;
- } else {
- return $this->redis->zrevrange($key, $start, $stop);
- }
- }
- /**
- *
- * 有序列表 - 获取指定积分区间内的成员
- * @param string $key
- * @param int/float $min
- * @param int/float $max
- * @param boolean $withScore
- * @param bool $limit 是否限制返回值大小
- * @param int $offset 限制返回结果的起始位置
- * @param type $count 返回结果的数量
- * @return type
- */
- public function zrangebyscore($key, $min, $max, $withScore = false, $limit = false, $offset = 0, $count = 10) {
- self::debug();
- if ($limit) {
- if ($withScore) {
- return $this->redis->zrangebyscore($key, $min, $max, 'WITHSCORES', "LIMIT", $offset, $count);
- } else {
- return $this->redis->zrangebyscore($key, $min, $max, 'LIMIT', $offset, $count);
- }
- } else {
- if ($withScore) {
- return $this->redis->zrangebyscore($key, $min, $max, 'WITHSCORES');
- } else {
- return $this->redis->zrangebyscore($key, $min, $max);
- }
- }
- }
- /**
- *
- * 有序列表 - 获取按照倒序排序后指定积分区间内的成员
- * @param string $key
- * @param int/float $max
- * @param int/float $min
- * @param boolean $withScore
- * @param bool $limit 是否限制返回值大小
- * @param int $offset 限制返回结果的起始位置
- * @param type $count 返回结果的数量
- * @return type
- */
- public function zrevrangebyscore($key, $max, $min, $withScore = false, $limit = false, $offset = 0, $count = 10) {
- self::debug();
- if ($limit) {
- if ($withScore) {
- return $this->redis->zrevrangebyscore($key, $max, $min, 'WITHSCORES', "LIMIT", $offset, $count);
- } else {
- return $this->redis->zrevrangebyscore($key, $max, $min, 'LIMIT', $offset, $count);
- }
- } else {
- if ($withScore) {
- return $this->redis->zrevrangebyscore($key, $max, $min, 'WITHSCORES');
- } else {
- return $this->redis->zrevrangebyscore($key, $max, $min);
- }
- }
- }
- /**
- * 有序列表 - 根据元素反查排名
- * @param string $key
- * @param string $member
- * @return int
- */
- public function zrank($key, $member) {
- self::debug();
- return $this->redis->zrank($key, $member);
- }
- /**
- * 有序列表 - 查询某个成员的倒序排名
- * @param string $key
- * @param string $member
- * @return int
- */
- public function zrevrank($key, $member) {
- self::debug();
- return $this->redis->zrevrank($key, $member);
- }
- /**
- * 有序列表 - 根据元素反查积分
- * @param string $key
- * @param string $member
- * @return int/float
- */
- public function zscore($key, $member) {
- self::debug();
- return $this->redis->zscore($key, $member);
- }
- /**
- * 有序列表 - 移除元素
- * @param string $key
- * @param string $member
- */
- public function zrem($key, $member) {
- self::debug();
- $this->redis->zrem($key, $member);
- }
- /**
- * 有序列表 - 移除指定区间的元素
- * @param string $key
- * @param int $start
- * @param int $stop
- */
- public function zremrangebyrank($key, $start, $stop) {
- self::debug();
- $this->redis->zremrangebyrank($key, $start, $stop);
- }
- /**
- * 有序列表 - 移除指定积分区间的元素.
- * @param string $key
- * @param int/float $min
- * @param int/float $max
- */
- public function zremrangebyscore($key, $min, $max) {
- self::debug();
- $this->redis->zremrangebyscore($key, $min, $max);
- }
- /**
- * 有序列表 - 复制有序类表到一个新的key
- * @param string $key_source 源集合
- * @param string $key_new 目标集合
- */
- public function zcopy($key_source, $key_new) {
- self::debug();
- $this->redis->zunionstore($key_new, 1, $key_source);
- }
- // </editor-fold>
- //
- // <editor-fold defaultstate="collapsed" desc=" 其他api ">
- //
- /**
- * 重命名一个key(注意: 与move的区别, move是将数据迁移到其他db,rename相当于在当前db内move)
- * @param type $key
- * @param type $newkey
- * @return boolean
- */
- public function rename($key, $newkey) {
- self::debug();
- return $this->redis->rename($key, $newkey) == "ok";
- }
- /**
- * 给指定的key设置/更新生存时间
- * @param string $key
- * @param number $seconds
- * @return bool
- */
- public function expire($key, $seconds) {
- self::debug();
- return $this->redis->expire($key, $seconds) == "ok";
- }
- // == end of zSet ===
- // * @method string zincrby($key, $increment, $member)
- // * @method int zinterstore($destination, array $keys, array $options = null)
- // * @method array zrevrangebyscore($key, $min, $max, array $options = null)
- // * @method int zunionstore($destination, array $keys, array $options = null)
- // * @method array zscan($key, $cursor, array $options = null)
- // * @method array zrangebylex($key, $start, $stop, array $options = null)
- // * @method int zremrangebylex($key, $min, $max)
- // === end of zSet 操作 =====
- // ======= hash 操作 ======
- //
- // // ======== set 操作 ======
- // * @method array sdiff(array $keys)
- // * @method int sdiffstore($destination, array $keys)
- // * @method array sinter(array $keys)
- // * @method int sinterstore($destination, array $keys)
- //
- // * @method int smove($source, $destination, $member)
- // * @method string spop($key)
- // * @method array sscan($key, $cursor, array $options = null)
- // * @method array sunion(array $keys)
- // * @method int sunionstore($destination, array $keys)
- // ======= 订阅相关api =======s
- // * @method int pfadd($key, array $elements)
- // * @method mixed pfmerge($destinationKey, array $sourceKeys)
- // * @method int pfcount(array $keys)
- // * @method mixed pubsub($subcommand, $argument)
- // * @method int publish($channel, $message)
- // *
- // ======= 事务相关api =======
- // * @method mixed discard()
- public function discard() {
- return $this->redis->discard();
- }
- // * @method array exec()
- // * @method mixed multi()
- // * @method mixed unwatch()
- // * @method mixed watch($key)
- // ======= 执行lua脚本 =======
- // * @method mixed eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
- // * @method mixed evalsha($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
- // * @method mixed script($subcommand, $argument = null)
- // ======= 服务器操作api ======
- // * @method mixed auth($password)
- // * @method string echo($message)
- // * @method mixed ping($message = null)
- // * @method mixed select($database)
- // * @method mixed bgrewriteaof()
- // * @method mixed bgsave()
- // </editor-fold>
- }
|