CRedisUtil.php 35 KB

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