CRedisUtil.php 37 KB

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