CRedisUtil.php 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161
  1. <?php
  2. namespace loyalsoft;
  3. //define('Redis_Debug', true); // 调试redis操作
  4. require __DIR__ . '/Predis/Autoloader.php';
  5. \Predis\Autoloader::register();
  6. /**
  7. * redis操作封装,
  8. * 关于阿里云redis的支持命令和未开放命令见:
  9. * https://docs.aliyun.com/?spm=5176.7630237.9.3.WfKF0A#/pub/kvstore/quick-start/kvstore-redis-command
  10. * 腾讯云支持的命令:
  11. * https://www.qcloud.com/doc/product/239/%E4%BD%BF%E7%94%A8%E9%99%90%E5%88%B6
  12. * redis相关命令说明见:http://redisdoc.com/
  13. *
  14. * 支持命令集接口见: /phpRedisAdmin/predis/src/ClientInterface.php
  15. * @version <br/>
  16. * 1.0.3 扩展list相关api的操作方法, 针对values统一做json编解码处理.
  17. * 整理其他数据结构的操作方法, normal/hash/list api内部做json编解码处理,
  18. * set/zset value 默认不做json编解码处理, 针对set/zset的value,不推荐写入太大或复杂的数据.
  19. * gwang 2017年4月28日 <br/>
  20. * 1.0.2 扩充特有数据结构的操作方法, gwang 2016.4.21 <br/>
  21. * 1.0.1 扩充了事务的使用方法.开发竞争类业务,圣树争夺战, gwang 2016.3.21 <br/>
  22. * 1.0.0 pguan,基础功能, 方法与memcache看齐. <br/>
  23. */
  24. class CRedisUtil extends CMemBase {
  25. public $keyDic = null;
  26. /**
  27. *
  28. * @var ClientInterface
  29. */
  30. public $redis = null;
  31. /**
  32. * 自动回收
  33. */
  34. function __destruct() {
  35. $this->close();
  36. }
  37. private static function debug() {
  38. if (defined('Redis_Debug') && Redis_Debug) {
  39. DebugHelper::print_stack_trace();
  40. }
  41. }
  42. // <editor-fold defaultstate="collapsed" desc=" 实现CMemBase操作接口">
  43. /**
  44. * 添加一个值
  45. * @param string $key
  46. * @param string $value
  47. * @param int $ts=0 此值无效
  48. * @return true 成功, false 失败,此key已经存在
  49. */
  50. public function add($key, $value, $ts = 0) {
  51. self::debug();
  52. return $this->setnx($key, JsonUtil::encode($value));
  53. }
  54. /**
  55. * 复制一个变量到另一个key
  56. * @param string $surKey 源数据的key
  57. * @param string $desKey 目的数据的key
  58. */
  59. public function copy($surKey, $desKey) {
  60. self::debug();
  61. return $this->set($desKey, $this->get($surKey));
  62. }
  63. /**
  64. * 一次取多个值
  65. * @param array(string) $keys
  66. * @return array
  67. */
  68. public function getMulti($keys) {
  69. self::debug();
  70. // var_dump($keys);
  71. return $this->mget($keys);
  72. }
  73. /**
  74. * 设置多个值
  75. * @param dic $dict [{"key":value},{"key":value},....]
  76. * @param int $expireTs=0 此值无效
  77. * @return true 永远成功
  78. */
  79. public function setMutlti($dict, $expireTs = 0) {
  80. self::debug();
  81. $params = array();
  82. foreach ($dict as $key => $val) {
  83. $params[$key] = is_string($val) ? $val : JsonUtil::encode($val);
  84. }
  85. if (count($params) <= 0) {
  86. return TRUE;
  87. }
  88. $this->mset($params);
  89. return true;
  90. }
  91. /**
  92. * 替换某个值
  93. * @param string $key
  94. * @param string $value
  95. * @param int $ts
  96. * @return boolean true 成功,false 失败
  97. */
  98. public function replace($key, $value, $ts = 0) {
  99. self::debug();
  100. $ret = $this->redis->setex($key, $value, $ts);
  101. if (strtolower($ret) == "ok") {
  102. return true;
  103. }
  104. $this->logErr($ret);
  105. return false;
  106. }
  107. /**
  108. * 不经过jsonencode直接存储
  109. * @deprecated since version 20160413113950 经过自己考察json_encode对数据的影响并不存在
  110. * @param type $key
  111. * @return any
  112. */
  113. public function getWithoutJson($key) {
  114. self::debug();
  115. return $this->redis->get($key);
  116. }
  117. /**
  118. * 不经过jsondecode直接返回
  119. * @deprecated since version 20160413113950 经过自己考察json_encode对数据的影响并不存在
  120. * @param string $key
  121. * @param string $value
  122. * @param int $ts
  123. * @return boolean
  124. */
  125. public function setWithoutJson($key, $value, $ts = 0) {
  126. self::debug();
  127. $ret = $this->redis->set($key, $value, $ts);
  128. if (strtolower($ret) == "ok") {
  129. return true;
  130. }
  131. $this->logErr($ret);
  132. return false;
  133. }
  134. /**
  135. * 输出日志
  136. * @param mixed $msg
  137. */
  138. private function logErr($msg) {
  139. CLog::err($msg, "Redis Err:");
  140. }
  141. /**
  142. * 连接
  143. * @param string $host
  144. * @param string $port
  145. * @param string $pwd
  146. * @return \CRedisUtil
  147. */
  148. public function conn($host, $port, $pwd = "") {
  149. // DebugHelper::print_stack_trace();
  150. $this->redis = new \Predis\Client(array(
  151. 'scheme' => 'tcp',
  152. 'host' => $host,
  153. 'port' => $port,
  154. 'password' => $pwd,
  155. ));
  156. $this->keyDic = new \stdClass();
  157. return $this;
  158. }
  159. /**
  160. * 关闭连接
  161. */
  162. public function close() {
  163. $this->redis->quit();
  164. }
  165. /**
  166. * 获取指定键值
  167. * @param string $key
  168. * @return any json_decode($result)
  169. */
  170. public function get($key) {
  171. self::debug();
  172. $result = $this->redis->get($key);
  173. if (!$result || $result == "" || $result == null) {
  174. return null;
  175. }
  176. $this->keyDic->$key = $result;
  177. return JsonUtil::decode($result);
  178. }
  179. /**
  180. * 将字符串值 $val 关联到 key
  181. * @param string $key
  182. * @param any $value
  183. * @param int $ts default(0) 过期时间(单位秒)
  184. * @return boolean 成功true,失败false
  185. */
  186. public function set($key, $value, $ts = 0) {
  187. self::debug();
  188. if ($value === null || $value === "") { # 这里必须用全等符号
  189. return false;
  190. }
  191. if (is_string($value)) { # 使用json序列化后存储
  192. $val = $value;
  193. } else {
  194. $val = JsonUtil::encode($value);
  195. }
  196. if ($ts > 0) { # 将会设置TTL 到期删除 ps: replaced by gwang 增加过期时间
  197. $ret = $this->redis->setex($key, $ts, $val);
  198. } else { # 0:永不过期,如果原来有TTL将会清除TTL.
  199. $ret = $this->redis->set($key, $val);
  200. }
  201. if ("OK" != $ret) {
  202. $this->logErr($ret);
  203. return false;
  204. }
  205. return true;
  206. }
  207. /**
  208. * 安全的写入操作
  209. * @deprecated since version 1.0 云平台暂时不支持
  210. * @param string $key
  211. * @param any $value
  212. * @return boolean 成功true,失败false
  213. */
  214. public function cas($key, $value, $ts = 0) {
  215. if (false) { # ps. 各云平台皆不支持eval方法执行lua脚本.等开放支持的时候才是真正支持cas的时候
  216. $castoken = $this->keyDic->$key;
  217. # # 定义一段脚本
  218. $script = <<<casscript
  219. if redis.call("get",KEYS[1]) == "$castoken"
  220. then
  221. return redis.call("set",KEYS[1],ARGV[1])
  222. else
  223. return 0
  224. end
  225. casscript;
  226. $ret = $this->redis->eval($script, 1, $key, $value); # redis 执行lua脚本
  227. if (0 == $ret) {
  228. return false;
  229. }
  230. return true;
  231. }
  232. // 非线程安全,原因见下
  233. return $this->set($key, $value, $ts);
  234. }
  235. /**
  236. * 删除一个或多个指定键值
  237. * @param string $keys
  238. * @return int 删除键的个数
  239. */
  240. public function delete($key) {
  241. self::debug();
  242. $infos = array();
  243. array_push($infos, $key);
  244. return $this->redis->del($infos);
  245. }
  246. // </editor-fold>
  247. //
  248. // <editor-fold defaultstate="collapsed" desc=" normal 普通对象操作 mget/mset">
  249. /**
  250. * 返回所有(一个或多个)给定 key 的值
  251. * 如果给定的 key 里面,有某个 key 不存在,那么这个 key 返回特殊值 nil 。因此,该命令永不失败。
  252. * @param array $keys
  253. * @return array 一个包含所有给定 key 的值的列表
  254. */
  255. private function mget($keys) {
  256. // self::debug();
  257. $ret = array();
  258. if (count($keys)) {
  259. $ctx = $this->redis->mget($keys);
  260. $mval = count($ctx);
  261. for ($i = 0; $i < $mval; $i++) {
  262. $ret[] = JsonUtil::decode($ctx[$i]);
  263. }
  264. }
  265. return $ret;
  266. }
  267. /**
  268. * Add函数拥有相同效果 \n
  269. * 将 key 的值设为 value ,当且仅当 key 不存在。
  270. * 若给定的 key 已经存在,则不做任何动作。
  271. * @param type $key
  272. * @param type $val
  273. * @return boolean 成功true,失败false
  274. */
  275. private function setnx($key, $val) {
  276. self::debug();
  277. $ret = $this->redis->setnx($key, $val);
  278. // 成功返回1, 失败返回0
  279. if (1 == $ret) {
  280. return true;
  281. }
  282. $this->logErr($ret);
  283. return false;
  284. }
  285. /**
  286. * 同时设置一个或多个 key-value 对
  287. * 如果某个给定 key 已经存在,那么 MSET 会用新值覆盖原来的旧值
  288. * @param array $dict
  289. * @return mixed
  290. */
  291. private function mset($dict) {
  292. self::debug();
  293. return $this->redis->mset($dict);
  294. }
  295. /**
  296. * 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在
  297. * 即使只有一个给定 key 已存在, MSETNX 也会拒绝执行所有给定 key 的设置操作
  298. *
  299. * @param array $dict
  300. * @return int
  301. */
  302. public function msetnx($dict) {
  303. self::debug();
  304. $ret = $this->redis->msetnx($dict);
  305. return $ret == 1;
  306. }
  307. /**
  308. * 检测指定键值是否存在
  309. * @param type $key
  310. * @return boolean true 存在, false 不存在
  311. */
  312. public function exists($key) {
  313. self::debug();
  314. return $this->redis->exists($key) == 1;
  315. }
  316. /**
  317. * 将 key 中储存的数字值增一
  318. * 如果 key 不存在,那么 key 的值会先被初始化为 0
  319. * 如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误
  320. * 本操作的值限制在 64 位(bit)有符号数字表示之内
  321. * @param type $key
  322. * @return int 执行 INCR 命令之后 key 的值
  323. */
  324. public function increment($key) {
  325. self::debug();
  326. return $this->redis->incr($key);
  327. }
  328. /**
  329. * 将 key 中储存的数字值增加 一个int值
  330. * 如果 key 不存在,那么 key 的值会先被初始化为 0
  331. * 如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误
  332. * 本操作的值限制在 64 位(bit)有符号数字表示之内
  333. * @param string $key
  334. * @param int $i 增加的值
  335. * @return int 执行 INCR 命令之后 key 的值
  336. */
  337. public function incrby($key, $i) {
  338. self::debug();
  339. return $this->redis->incrby($key, $i);
  340. }
  341. // </editor-fold>
  342. //
  343. //======================== 以下部分 added by gwang at 2016-4-14 15:17:25 =================
  344. // <editor-fold defaultstate="collapsed" desc=" 辅助函数 ">
  345. /**
  346. * Server功能,看服务器是否连通
  347. * @return boolean true连通正常
  348. */
  349. public function ping() {
  350. $ret = $this->redis->ping();
  351. if ($ret == "PONG") {
  352. return true;
  353. }
  354. $this->logErr($ret);
  355. return false;
  356. }
  357. /**
  358. * 对数组进行json编码
  359. * @param array $values
  360. * @return array
  361. */
  362. static private function json_encode_arr($values) {
  363. $arr = array();
  364. if (is_array($values)) {
  365. $arr = array_map(function($v) {
  366. return JsonUtil::encode($v);
  367. }, $values);
  368. } else {
  369. $arr[] = JsonUtil::encode($values);
  370. }
  371. return $arr;
  372. }
  373. /**
  374. * 对数组进行json解码
  375. * @param array $values
  376. * @return array
  377. */
  378. static private function json_decode_arr(array $values) {
  379. $arr = array();
  380. if (is_array($values)) {
  381. $arr = array_map(function($v) {
  382. return JsonUtil::decode($v);
  383. }, $values);
  384. } else {
  385. $arr[] = JsonUtil::decode($values);
  386. }
  387. return $arr;
  388. }
  389. // </editor-fold>
  390. //
  391. // <editor-fold defaultstate="collapsed" desc=" 事务操作 ">
  392. /**
  393. * 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
  394. * @param string $key
  395. */
  396. public function watch($key) {
  397. $this->redis->watch($key);
  398. }
  399. /**
  400. * 取消监视
  401. */
  402. public function unwatch() {
  403. $this->redis->unwatch();
  404. }
  405. /**
  406. * 开启事务
  407. */
  408. public function multi() {
  409. $this->redis->multi();
  410. }
  411. /**
  412. * 执行事务
  413. * @return type 事务块内所有命令的返回值,按命令执行的先后顺序排列。当操作被打断时,返回空值 nil 。
  414. */
  415. public function exec() {
  416. return $this->redis->exec();
  417. }
  418. // </editor-fold>
  419. //
  420. // == ↓ 下面是Redis独有的数据类型操作 ↓ ==
  421. //
  422. // <editor-fold defaultstate="collapsed" desc=" set 集合操作 ">
  423. /**
  424. * 集合(set) - 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。
  425. * 集合不存在时将会创建集合
  426. * @param string $key
  427. * @param string[] $members (mixed is ok, i will transmit it.)
  428. * @return int
  429. * @expectedException type not set error
  430. */
  431. public function sadd($key, $members) {
  432. self::debug();
  433. if (!is_array($members)) { # 防御: 参数不为数组
  434. if (!is_string($members)) { # 防御: 参数不为字符串
  435. $members = JsonUtil::encode($members);
  436. }
  437. $members = array($members); # 转为字符串数组
  438. }
  439. return $this->redis->sadd($key, $members);
  440. }
  441. /**
  442. * 集合(set) - 将一个或多个 member 元素从集合 key 当中移除
  443. * 集合不存在时将会创建集合
  444. * @param string $key
  445. * @param string[] $members
  446. * @return int
  447. * @expectedException type not set error
  448. */
  449. public function sremove($key, $members) {
  450. self::debug();
  451. return $this->redis->srem($key, $members);
  452. }
  453. /**
  454. * 集合(set) - 返回集合 key 的基数(集合中元素的数量)。
  455. * @param strig $key
  456. * @return int
  457. */
  458. public function scard($key) {
  459. self::debug();
  460. return $this->redis->scard($key);
  461. }
  462. /**
  463. * 集合(set) - 等效于scard: 返回集合 key 的基数(集合中元素的数量)。
  464. * @param string $key
  465. * @return int
  466. *
  467. */
  468. public function slen($key) {
  469. self::debug();
  470. return $this->scard($key);
  471. }
  472. /**
  473. * 集合(set) - 判断某个元素是否属于集合
  474. * @param string $key
  475. * @param string $member
  476. * @return bool
  477. */
  478. public function sismember($key, $member) {
  479. self::debug();
  480. return $this->redis->sismember($key, $member) == 1;
  481. }
  482. /**
  483. * 集合(set) - 返回集合 key 中的所有成员。
  484. * @param type $key
  485. * @return array 不存在的key视为空集合
  486. */
  487. public function smembers($key) {
  488. self::debug();
  489. return $this->redis->smembers($key);
  490. }
  491. /**
  492. * 集合(set) - 如果命令执行时,只提供了 key 参数,那么返回集合中的10个随机元素。
  493. * 如果 count 为正数,且小于集合基数,那么命令返回一个包含 count 个元素的数组,数组中的元素各不相同。如果 count 大于等于集合基数,那么返回整个集合。
  494. * 如果 count 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值。
  495. * @param string $key
  496. * @param int $count =10
  497. * @return array
  498. */
  499. public function srandmember($key, $count = 10) {
  500. self::debug();
  501. return $this->redis->srandmember($key, $count);
  502. }
  503. // </editor-fold>
  504. //
  505. // <editor-fold defaultstate="collapsed" desc=" hash 哈希表操作 ">
  506. /**
  507. * 哈希表 - 删除 字段
  508. * @param string $key
  509. * @param array $fields
  510. * @return int 删除的字段的数量
  511. */
  512. public function hdel($key, $fields) {
  513. self::debug();
  514. return $this->redis->hdel($key, $fields);
  515. }
  516. /**
  517. * 哈希表 - 判断field是否存在
  518. * @param string $key
  519. * @param string $field
  520. * @return boolean true=存在,false 找不到
  521. */
  522. public function hexists($key, $field) {
  523. self::debug();
  524. return $this->redis->hexists($key, $field) == 1;
  525. }
  526. /**
  527. * 哈希表 - 获取字段
  528. * @param string $key
  529. * @param string $field 字段名
  530. * @return mixed json_decoded object
  531. */
  532. public function hget($key, $field) {
  533. self::debug();
  534. // echo $field, $key;
  535. $ret = $this->redis->hget($key, $field);
  536. // var_dump($ret);
  537. return JsonUtil::decode($ret);
  538. }
  539. /**
  540. * 哈希表 - 获取所有字段
  541. * @param string $key
  542. * @return stdclass/associate_array (适用箭头取变量写法)
  543. */
  544. public function hgetall($key) {
  545. self::debug();
  546. $ret = ArrayInit();
  547. $arr = $this->redis->hgetall($key);
  548. foreach ($arr as $k => $v) {
  549. $ret[$k] = JsonUtil::decode($v);
  550. }
  551. // 转为关联数组({})再返回, 方便代码中使用箭头写法
  552. return JsonUtil::decode(JsonUtil::encode($ret));
  553. }
  554. /**
  555. * 哈希表 - 获取表中字段数量
  556. * @param string $key
  557. * @return int
  558. */
  559. public function hlen($key) {
  560. self::debug();
  561. return $this->redis->hlen($key);
  562. }
  563. /**
  564. * 哈希表 - 同时获取多个字段
  565. * @param string $key
  566. * @param array $fields
  567. * @return Array
  568. */
  569. public function hmget($key, $fields) {
  570. self::debug();
  571. $ret = ArrayInit();
  572. if (is_array($fields) && count($fields) > 0) {
  573. $arr = $this->redis->hmget($key, $fields);
  574. foreach ($arr as $k => $v) {
  575. $ret[$k] = JsonUtil::decode($v);
  576. }
  577. }
  578. // 转为关联数组({})再返回, 方便代码中使用箭头写法
  579. return JsonUtil::decode(JsonUtil::encode($ret));
  580. }
  581. /**
  582. * 哈希表 - 同时设置多个字段的值
  583. * @param string $key
  584. * @param assoc_array $dictionary
  585. * @return boolean true成功
  586. */
  587. public function hmset($key, $dictionary) {
  588. self::debug();
  589. $newdic = ArrayInit();
  590. foreach ($dictionary as $k => $v) {
  591. $newdic[$k] = JsonUtil::encode($v);
  592. }
  593. $ret = $this->redis->hmset($key, $newdic);
  594. if (strtolower($ret) == 'ok') {
  595. return true;
  596. }
  597. return false;
  598. }
  599. /**
  600. * 哈希表 - 设置或新建一个字段的值
  601. * @param string $key
  602. * @param string $field
  603. * @param $mixed $value
  604. * @return int 0 覆盖旧值, 1 新建字段
  605. */
  606. public function hset($key, $field, $value) {
  607. self::debug();
  608. return $this->redis->hset($key, $field, JsonUtil::encode($value));
  609. }
  610. /**
  611. * 哈希表 - 增加一个新的field,已经存在则放弃操作返回false
  612. * @param string $key
  613. * @param string $field
  614. * @param string $value
  615. * @return boolean true成功
  616. */
  617. public function hsetnx($key, $field, $value) {
  618. self::debug();
  619. return $this->redis->hsetnx($key, $field, JsonUtil::encode($value)) == 1;
  620. }
  621. /**
  622. * 哈希表 - 按字段赠加 int值
  623. * @param string $key
  624. * @param string $field
  625. * @param int $increment
  626. * @return int
  627. */
  628. public function hincrby($key, $field, $increment) {
  629. self::debug();
  630. return $this->redis->hincrby($key, $field, $increment);
  631. }
  632. /**
  633. * 哈希表 - 按字段增加 float值
  634. * @param string $key
  635. * @param string $field
  636. * @param string $increment float值用string
  637. * @return string 用string存float值
  638. */
  639. public function hincrbyfloat($key, $field, $increment) {
  640. self::debug();
  641. return $this->redis->hincrbyfloat($key, $field, $increment);
  642. }
  643. /**
  644. * @param string $key
  645. * @return array
  646. */
  647. public function hkeys($key) {
  648. self::debug();
  649. return $this->redis->hkeys($key);
  650. }
  651. // * @method array hscan($key, $cursor, array $options = null)
  652. // * @method array hvals($key)
  653. // </editor-fold>
  654. //
  655. // <editor-fold defaultstate="collapsed" desc=" list 链表操作 ">
  656. //
  657. // <editor-fold defaultstate="collapsed" desc=" 阻塞的链表操作 ">
  658. /**
  659. * 链表 - 阻塞弹出, 当列表中没有元素的时候,命令会阻塞,直到等待超时或者有元素被添加到列表中.
  660. * @param array $keys 可以指定多个数组
  661. * @param int $timeout
  662. * @return array
  663. */
  664. public function blpop(array $keys, $timeout) {
  665. self::debug();
  666. $arr = $this->redis->blpop($keys, $timeout);
  667. $arr[1] = JsonUtil::decode($arr[1]); // 对value进行解包
  668. return $arr;
  669. }
  670. /**
  671. * 链表 - 阻塞队尾弹出, 当列表中没有元素的时候,命令会阻塞,直到等待超时或者有元素被添加到列表中.
  672. * @return array
  673. */
  674. public function brpop(array $keys, $timeout) {
  675. self::debug();
  676. $arr = $this->redis->brpop($keys, $timeout);
  677. $arr[1] = JsonUtil::decode($arr[1]);
  678. return $arr;
  679. }
  680. /**
  681. * 链表 - 阻塞版的 队尾弹出插入到队首. 本操作是原子的.
  682. *
  683. * @return array 假如在指定时间内没有任何元素被弹出,则返回一个 nil 和等待时长。
  684. * 反之,返回一个含有两个元素的列表,第一个元素是被弹出元素的值,第二个元素是等待时长。
  685. */
  686. public function brpoplpush($source, $destination, $timeout) {
  687. self::debug();
  688. $arr = $this->redis > brpoplpush($source, $destination, $timeout);
  689. $arr[0] = JsonUtil::decode($arr[0]);
  690. return $arr;
  691. }
  692. // </editor-fold>
  693. //
  694. /**
  695. * 链表 - 返回下标为index的元素
  696. * @return string
  697. */
  698. public function lindex($key, $index) {
  699. self::debug();
  700. $a = $this->redis->lindex($key, $index);
  701. return JsonUtil::decode($a);
  702. }
  703. /**
  704. * 链表 - 返回 链表key的长度
  705. * @return int
  706. * @param type $key
  707. */
  708. public function llen($key) {
  709. self::debug();
  710. return $this->redis->llen($key);
  711. }
  712. /**
  713. * 链表 - 移除并返回链表的队首元素.
  714. * @return string
  715. * @param type $key
  716. */
  717. public function lpop($key) {
  718. self::debug();
  719. $a = $this->redis->lpop($key);
  720. return JsonUtil::decode($a);
  721. }
  722. /**
  723. * 链表 - 向链表插入一个或多个值,链表不存在时创建链表并插入元素
  724. * @return int key存在却不是链表类型时返回一个错误.
  725. * @param type $key
  726. * @param array $values
  727. */
  728. public function lpush($key, $values) {
  729. self::debug();
  730. $arr = self::json_encode_arr($values);
  731. return $this->redis->lpush($key, $arr);
  732. }
  733. /**
  734. * 链表 - 取链表中指定下标区间的元素
  735. * @return array
  736. * @param string $key
  737. * @param int $start
  738. * @param int $stop
  739. */
  740. public function lrange($key, $start, $stop) {
  741. self::debug();
  742. $values = $this->redis->lrange($key, $start, $stop);
  743. return self::json_decode_arr($values);
  744. }
  745. /**
  746. * 链表 - 移除链表中 count 个值为 value的元素.
  747. * @return int
  748. * @param string $key
  749. * @param int $count
  750. * @param string $value
  751. */
  752. public function lrem($key, $count, $value) {
  753. self::debug();
  754. return $this->redis->lrem($key, $count, JsonUtil::encode($value));
  755. }
  756. /**
  757. * 链表 - 将链表中下标为index的 元素设置为value
  758. * @return mixed
  759. *
  760. * @param type $key
  761. * @param type $index
  762. * @param type $value
  763. */
  764. public function lset($key, $index, $value) {
  765. self::debug();
  766. return $this->redis->lset($key, $index, JsonUtil::encode($value));
  767. }
  768. /**
  769. * 链表 - 对链表进行修剪, 让链表只保留指定下标区间的元素,其余元素删除
  770. * @return bool true 成功, false 失败
  771. * @param string $key
  772. * @param int $start
  773. * @param int $stop
  774. */
  775. public function ltrim($key, $start, $stop) {
  776. self::debug();
  777. // return mixed: ok or fails
  778. $ret = $this->redis->ltrim($key, $start, $stop);
  779. if (strtolower($ret) == 'ok') {
  780. return true;
  781. }
  782. return false;
  783. }
  784. /**
  785. * 链表 - 从链表右侧(尾部)弹出一个元素,并返回该元素
  786. * @param string $key
  787. * @return string 列表的尾元素。当 key 不存在时,返回 nil
  788. */
  789. public function rpop($key) {
  790. self::debug();
  791. return JsonUtil::decode($this->redis->rpop($key));
  792. }
  793. /**
  794. * 将一个或多个值 value 插入到列表 key 的表尾(最右边)。
  795. * @param string $key
  796. * @param array $values
  797. * @return int
  798. */
  799. public function rpush($key, array $values) {
  800. self::debug();
  801. $arr = self::json_encode_arr($values);
  802. return $this->redis->rpush($key, $arr);
  803. }
  804. //
  805. // /**
  806. // * 链表 - 向链表中插入一个或多个值,链表不存在时,什么也不做.
  807. // * @return int
  808. // * @param type $key
  809. // * @param type $value
  810. // */
  811. // public function lpushx($key, $value)
  812. // {
  813. // return $this->redis->lpushx($key, $value);
  814. // }
  815. // /**
  816. // * 链表 - 将值 value 插入到链表 key 中 , 位于pivot之前或之后
  817. // * @return int -1:未找到pivot, 0:链表为空或者不存在.
  818. // *
  819. // * @param string $key 链表名称
  820. // * @param string $whence after/before pivot之前或之后
  821. // * @param string $pivot 插入pivot之前或之后
  822. // * @param string $value 要插入的value
  823. // */
  824. // public function linsert($key, $whence, $pivot, $value)
  825. // {
  826. // $this->redis->linsert($key, $whence, $pivot, $value);
  827. // }
  828. // /**
  829. // * 在一个原子时间内,执行以下两个动作
  830. // * 将列表 source 中的最后一个元素(尾元素)弹出,并返回给客户端。
  831. // * 将 source 弹出的元素插入到列表 destination ,作为 destination 列表的的头元素.
  832. // * @return string
  833. // */
  834. // public function rpoplpush($source, $destination)
  835. // {
  836. // throw new Exception("un implemented now!");
  837. // }
  838. // /**
  839. // * 将值 value 插入到列表 key 的表尾,当且仅当 key 存在并且是一个列表。
  840. // * 和 RPUSH 命令相反,当 key 不存在时, RPUSHX 命令什么也不做。
  841. // * @param type $key
  842. // * @param type $value
  843. // * @return int
  844. // */
  845. // public function rpushx($key, $value)
  846. // {
  847. // throw new Exception("un implemented now!");
  848. // }
  849. // </editor-fold>
  850. //
  851. // <editor-fold defaultstate="collapsed" desc=" zset 有序集合 ">
  852. /**
  853. * 有序集合 - 添加或更新元素 对于zset类型不建议写入太长, 太复杂的value
  854. * @param string $key
  855. * @param array $membersAndScoresDictionary array( 'value'=>score,'value'=>score,...), score可以是int或float
  856. * @return int 新增元素数量,不包含更新的元素
  857. */
  858. public function zadd($key, $membersAndScoresDictionary) {
  859. self::debug();
  860. return $this->redis->zadd($key, $membersAndScoresDictionary);
  861. }
  862. /**
  863. * 有序集合 - 给某个元素增加积分
  864. * @param string $key
  865. * @param string $member
  866. * @param int $increment
  867. * @return string
  868. */
  869. public function zincrby($key, $member, $increment = 1) {
  870. self::debug();
  871. return $this->redis->zincrby($key, $increment, $member);
  872. }
  873. /**
  874. * 有序集合 - 元素数量
  875. * @param string $key
  876. * @return int
  877. */
  878. public function zlen($key) {
  879. self::debug();
  880. return $this->redis->zcard($key);
  881. }
  882. /**
  883. * 有序集合 - 统计某区间元素数量
  884. * @param string $key
  885. * @param int/float $min 最低分
  886. * @param int/float $max 最高分
  887. * @return int
  888. */
  889. public function zcount($key, $min, $max) {
  890. self::debug();
  891. return $this->redis->zcount($key, $min, $max);
  892. }
  893. /**
  894. * 有序集合 - 获取集合指定区间内的成员, 第一个成员从0开始
  895. * @param string $key
  896. * @param int $start
  897. * @param int $stop Ps.以 -1 表示最后一个成员, -2 表示倒数第二个成员
  898. * @param boolean $withScore 返回值中是否带score字段
  899. * @return array (index=>member) or assoc_array (member=>score)
  900. */
  901. public function zrange($key, $start, $stop, $withScore = false) {
  902. self::debug();
  903. if ($withScore) {
  904. return $this->redis->zrange($key, $start, $stop, 'WITHSCORES');
  905. } else {
  906. return $this->redis->zrange($key, $start, $stop);
  907. }
  908. if ($withScore) {
  909. $ret = $this->redis->zrange($key, $start, $stop, 'WITHSCORES');
  910. DebugHelper::var_dump($ret);
  911. $ma = count($ret);
  912. $arr = array();
  913. for ($i = 0; $i < $ma; $i += 2) {
  914. $arr[$ret[$i]] = $ret[$i + 1];
  915. }
  916. return $arr;
  917. } else {
  918. $ret = $this->redis->zrange($key, $start, $stop);
  919. DebugHelper::var_dump($ret);
  920. return $ret;
  921. }
  922. }
  923. /**
  924. *
  925. * 有序集合 - 获取集合倒序之后,指定区间内的成员, 第一个成员从0开始
  926. * @param string $key
  927. * @param int $start
  928. * @param int $stop Ps.以 -1 表示最后一个成员, -2 表示倒数第二个成员
  929. * @param boolean $withScore 返回值中是否带score字段 default(false)
  930. * @return array (index=>member) or assoc_array (member=>score)
  931. */
  932. public function zrevrange($key, $start, $stop, $withScore = false) {
  933. self::debug();
  934. if ($withScore) {
  935. echoLine("带分数取");
  936. $r = $this->redis->zrevrange($key, $start, $stop, 'WITHSCORES');
  937. var_dump($r);
  938. return $r;
  939. } else {
  940. return $this->redis->zrevrange($key, $start, $stop);
  941. }
  942. }
  943. /**
  944. * 有序列表 - 获取指定积分区间内的成员
  945. * @param string $key
  946. * @param int/float $min
  947. * @param int/float $max
  948. * @param boolean $withScore
  949. * @return type
  950. */
  951. public function zrangebyscore($key, $min, $max, $withScore = false) {
  952. self::debug();
  953. if ($withScore) {
  954. return $this->redis->zrangebyscore($key, $min, $max, 'WITHSCORES');
  955. } else {
  956. return $this->redis->zrangebyscore($key, $min, $max);
  957. }
  958. }
  959. /**
  960. * 有序列表 - 根据元素反查排名
  961. * @param string $key
  962. * @param string $member
  963. * @return int
  964. */
  965. public function zrank($key, $member) {
  966. self::debug();
  967. return $this->redis->zrank($key, $member);
  968. }
  969. /**
  970. * 有序列表 - 查询某个成员的倒序排名
  971. * @param string $key
  972. * @param string $member
  973. * @return int
  974. */
  975. public function zrevrank($key, $member) {
  976. self::debug();
  977. return $this->redis->zrevrank($key, $member);
  978. }
  979. /**
  980. * 有序列表 - 根据元素反查积分
  981. * @param string $key
  982. * @param string $member
  983. * @return int/float
  984. */
  985. public function zscore($key, $member) {
  986. self::debug();
  987. return $this->redis->zscore($key, $member);
  988. }
  989. /**
  990. * 有序列表 - 移除元素
  991. * @param string $key
  992. * @param string $member
  993. */
  994. public function zrem($key, $member) {
  995. self::debug();
  996. $this->redis->zrem($key, $member);
  997. }
  998. /**
  999. * 有序列表 - 移除指定区间的元素
  1000. * @param string $key
  1001. * @param int $start
  1002. * @param int $stop
  1003. */
  1004. public function zremrangebyrank($key, $start, $stop) {
  1005. self::debug();
  1006. $this->redis->zremrangebyrank($key, $start, $stop);
  1007. }
  1008. /**
  1009. * 有序列表 - 移除指定积分区间的元素.
  1010. * @param string $key
  1011. * @param int/float $min
  1012. * @param int/float $max
  1013. */
  1014. public function zremrangebyscore($key, $min, $max) {
  1015. self::debug();
  1016. $this->redis->zremrangebyscore($key, $min, $max);
  1017. }
  1018. // </editor-fold>
  1019. //
  1020. // <editor-fold defaultstate="collapsed" desc=" 其他api ">
  1021. // == end of zSet ===
  1022. // * @method string zincrby($key, $increment, $member)
  1023. // * @method int zinterstore($destination, array $keys, array $options = null)
  1024. // * @method array zrevrangebyscore($key, $min, $max, array $options = null)
  1025. // * @method int zunionstore($destination, array $keys, array $options = null)
  1026. // * @method array zscan($key, $cursor, array $options = null)
  1027. // * @method array zrangebylex($key, $start, $stop, array $options = null)
  1028. // * @method int zremrangebylex($key, $min, $max)
  1029. // === end of zSet 操作 =====
  1030. // ======= hash 操作 ======
  1031. //
  1032. // // ======== set 操作 ======
  1033. // * @method array sdiff(array $keys)
  1034. // * @method int sdiffstore($destination, array $keys)
  1035. // * @method array sinter(array $keys)
  1036. // * @method int sinterstore($destination, array $keys)
  1037. //
  1038. // * @method int smove($source, $destination, $member)
  1039. // * @method string spop($key)
  1040. // * @method array sscan($key, $cursor, array $options = null)
  1041. // * @method array sunion(array $keys)
  1042. // * @method int sunionstore($destination, array $keys)
  1043. // ======= 订阅相关api =======s
  1044. // * @method int pfadd($key, array $elements)
  1045. // * @method mixed pfmerge($destinationKey, array $sourceKeys)
  1046. // * @method int pfcount(array $keys)
  1047. // * @method mixed pubsub($subcommand, $argument)
  1048. // * @method int publish($channel, $message)
  1049. // *
  1050. // ======= 事务相关api =======
  1051. // * @method mixed discard()
  1052. // * @method array exec()
  1053. // * @method mixed multi()
  1054. // * @method mixed unwatch()
  1055. // * @method mixed watch($key)
  1056. // ======= 执行lua脚本 =======
  1057. // * @method mixed eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
  1058. // * @method mixed evalsha($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
  1059. // * @method mixed script($subcommand, $argument = null)
  1060. // ======= 服务器操作api ======
  1061. // * @method mixed auth($password)
  1062. // * @method string echo($message)
  1063. // * @method mixed ping($message = null)
  1064. // * @method mixed select($database)
  1065. // * @method mixed bgrewriteaof()
  1066. // * @method mixed bgsave()
  1067. // </editor-fold>
  1068. }