Predis.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. <?php
  2. /**
  3. * lemocms
  4. * ============================================================================
  5. * 版权所有 2018-2027 lemocms,并保留所有权利。
  6. * 网站地址: https://www.lemocms.com
  7. * ----------------------------------------------------------------------------
  8. * 采用最新Thinkphp6实现
  9. * ============================================================================
  10. * Author: yuege
  11. * Date: 2019/9/6
  12. */
  13. namespace lemo\service;
  14. use think\facade\Log;
  15. class Predis
  16. {
  17. public $redisObj = null;//redis实例化时静态变量
  18. static protected $instance;
  19. protected $sn;
  20. protected $index = 0;
  21. protected $port = 6379;
  22. protected $auth = "";
  23. protected $host = "127.0.0.1";
  24. public function __construct($options = [])
  25. {
  26. $host = trim(isset($options["host"]) ? $options["host"] : $this->host);
  27. $port = trim(isset($options["port"]) ? $options["port"] : $this->port);
  28. $auth = trim(isset($options["auth"]) ? $options["auth"] : $this->auth);
  29. $index = trim(isset($options["index"]) ? $options["index"] : $this->index);
  30. if (!is_integer($index) && $index > 16) {
  31. $index = 0;
  32. }
  33. $sn = md5("{$host}{$port}{$auth}{$index}");
  34. $this->sn = $sn;
  35. if (!isset($this->redisObj[$this->sn])) {
  36. try {
  37. $this->redisObj[$this->sn] = new \Redis();
  38. $this->redisObj[$this->sn]->connect($host, $port);
  39. $this->redisObj[$this->sn]->auth($auth);
  40. $this->redisObj[$this->sn]->select($index);
  41. } catch (\Exception $e) {
  42. Log::notice($e->getMessage());
  43. try {
  44. $this->redisObj[$this->sn] = new \Redis();
  45. $this->redisObj[$this->sn]->connect($host, $port);
  46. $this->redisObj[$this->sn]->auth($auth);
  47. $this->redisObj[$this->sn]->select($index);
  48. } catch (\Exception $e) {
  49. Log::error($e->getMessage());
  50. }
  51. }
  52. }
  53. $this->redisObj[$this->sn]->sn = $sn;
  54. $this->index = $index;
  55. return;
  56. }
  57. /**
  58. * Power: yue909
  59. * Email:994927909@qq.com
  60. * @param array $options
  61. * @return Redis
  62. */
  63. public static function instance($options = [])
  64. {
  65. return new Redis($options);
  66. }
  67. public function getKeys($key = '*')
  68. {
  69. return $this->redisObj[$this->sn]->getKeys($key);
  70. }
  71. public function setExpire($key, $time = 0)
  72. {
  73. if (!$key) {
  74. return false;
  75. }
  76. switch (true) {
  77. case ($time == 0):
  78. return $this->redisObj[$this->sn]->expire($key, 0);
  79. break;
  80. case ($time > time()):
  81. $this->redisObj[$this->sn]->expireAt($key, $time);
  82. break;
  83. default:
  84. return $this->redisObj[$this->sn]->expire($key, $time);
  85. }
  86. }
  87. /*------------------------------------start 1.string结构----------------------------------------------------*/
  88. /**
  89. * 增,设置值 构建一个字符串
  90. * @param string $key KEY名称
  91. * @param string $value 设置值
  92. * @param int $timeOut 时间 0表示无过期时间
  93. * @return true【总是返回true】
  94. */
  95. public function set($key, $value, $timeOut = 0)
  96. {
  97. $setRes = $this->redisObj[$this->sn]->set($key, $value);
  98. if ($timeOut > 0) $this->redisObj[$this->sn]->expire($key, $timeOut);
  99. return $setRes;
  100. }
  101. /**
  102. * 查,获取 某键对应的值,不存在返回false
  103. * @param $key ,键值
  104. * @return bool|string ,查询成功返回信息,失败返回false
  105. */
  106. public function get($key)
  107. {
  108. $setRes = $this->redisObj[$this->sn]->get($key);//不存在返回false
  109. if ($setRes === 'false') {
  110. return false;
  111. }
  112. return $setRes;
  113. }
  114. /*------------------------------------1.end string结构----------------------------------------------------*/
  115. /*------------------------------------2.start list结构----------------------------------------------------*/
  116. /**
  117. * 增,构建一个列表(先进后去,类似栈)
  118. * @param String $key KEY名称
  119. * @param string $value 值
  120. * @param $timeOut |num 过期时间
  121. */
  122. public function lPush($key, $value, $timeOut = 0)
  123. {
  124. // echo "$key - $value \n";
  125. $re = $this->redisObj[$this->sn]->LPUSH($key, $value);
  126. if ($timeOut > 0) $this->redisObj[$this->sn]->expire($key, $timeOut);
  127. return $re;
  128. }
  129. /**
  130. * 增,构建一个列表(先进先去,类似队列)
  131. * @param string $key KEY名称
  132. * @param string $value 值
  133. * @param $timeOut |num 过期时间
  134. */
  135. public function rPush($key, $value, $timeOut = 0)
  136. {
  137. // echo "$key - $value \n";
  138. $re = $this->redisObj[$this->sn]->RPUSH($key, $value);
  139. if ($timeOut > 0) $this->redisObj[$this->sn]->expire($key, $timeOut);
  140. return $re;
  141. }
  142. /**
  143. * 查,获取所有列表数据(从头到尾取)
  144. * @param string $key KEY名称
  145. * @param int $head 开始
  146. * @param int $tail 结束
  147. */
  148. public function lRanges($key, $head, $tail)
  149. {
  150. return $this->redisObj[$this->sn]->lrange($key, $head, $tail);
  151. }
  152. /**
  153. * Power by yue909
  154. * QQ:994927909
  155. * @param $key
  156. * @return mixed
  157. */
  158. public function rPop($key)
  159. {
  160. return $this->redisObj[$this->sn]->rPop($key);
  161. }
  162. public function lPop($key)
  163. {
  164. return $this->redisObj[$this->sn]->lpop($key);
  165. }
  166. /*------------------------------------2.end list结构----------------------------------------------------*/
  167. /*------------------------------------3.start set结构----------------------------------------------------*/
  168. /**
  169. * 增,构建一个集合(无序集合)
  170. * @param string $key 集合Y名称
  171. * @param string|array $value 值
  172. * @param int $timeOut 时间 0表示无过期时间
  173. * @return
  174. */
  175. public function sAdd($key, $value, $timeOut = 0)
  176. {
  177. $re = $this->redisObj[$this->sn]->sadd($key, $value);
  178. if ($timeOut > 0) $this->redisObj[$this->sn]->expire($key, $timeOut);
  179. return $re;
  180. }
  181. /**
  182. * 查,取集合对应元素
  183. * @param string $key 集合名字
  184. */
  185. public function sMembers($key)
  186. {
  187. $re = $this->redisObj[$this->sn]->exists($key);//存在返回1,不存在返回0
  188. if (!$re) return false;
  189. return $this->redisObj[$this->sn]->smembers($key);
  190. }
  191. /*------------------------------------3.end set结构----------------------------------------------------*/
  192. /*------------------------------------4.start sort set结构----------------------------------------------------*/
  193. /*
  194. * 增,改,构建一个集合(有序集合),支持批量写入,更新
  195. * @param string $key 集合名称
  196. * @param array $score_value key为scoll, value为该权的值
  197. * @return int 插入操作成功返回插入数量【,更新操作返回0】
  198. */
  199. public function zadd($key, $score_value, $timeOut = 0)
  200. {
  201. if (!is_array($score_value)) return false;
  202. $a = 0;//存放插入的数量
  203. foreach ($score_value as $score => $value) {
  204. $re = $this->redisObj[$this->sn]->zadd($key, $score, $value);//当修改时,可以修改,但不返回更新数量
  205. $re && $a += 1;
  206. if ($timeOut > 0) $this->redisObj[$this->sn]->expire($key, $timeOut);
  207. }
  208. return $a;
  209. }
  210. /**
  211. * 查,有序集合查询,可升序降序,默认从第一条开始,查询一条数据
  212. * @param $key ,查询的键值
  213. * @param $min ,从第$min条开始
  214. * @param $max,查询的条数
  215. * @param $order ,asc表示升序排序,desc表示降序排序
  216. * @return array|bool 如果成功,返回查询信息,如果失败返回false
  217. */
  218. public function zRange($key, $min = 0, $num = 1, $order = 'desc')
  219. {
  220. $re = $this->redisObj[$this->sn]->exists($key);//存在返回1,不存在返回0
  221. if (!$re) return false;//不存在键值
  222. if ('desc' == strtolower($order)) {
  223. $re = $this->redisObj[$this->sn]->zrevrange($key, $min, $min + $num - 1);
  224. } else {
  225. $re = $this->redisObj[$this->sn]->zrange($key, $min, $min + $num - 1);
  226. }
  227. if (!$re) return false;//查询的范围值为空
  228. return $re;
  229. }
  230. /**
  231. * 返回集合key中,成员member的排名
  232. * @param $key,键值
  233. * @param $member,scroll值
  234. * @param $type ,是顺序查找还是逆序
  235. * @return bool,键值不存在返回false,存在返回其排名下标
  236. */
  237. public function zrank($key, $member, $type = 'desc')
  238. {
  239. $type = strtolower(trim($type));
  240. if ($type == 'desc') {
  241. $re = $this->redisObj[$this->sn]->zrevrank($key, $member);//其中有序集成员按score值递减(从大到小)顺序排列,返回其排位
  242. } else {
  243. $re = $this->redisObj[$this->sn]->zrank($key, $member);//其中有序集成员按score值递增(从小到大)顺序排列,返回其排位
  244. }
  245. if (!is_numeric($re)) return false;//不存在键值
  246. return $re;
  247. }
  248. /**
  249. * 返回名称为key的zset中score >= star且score <= end的所有元素
  250. * @param $key
  251. * @param $member
  252. * @param $star,
  253. * @param $end ,
  254. * @return array
  255. */
  256. public function zrangbyscore($key, $star, $end)
  257. {
  258. return $this->redisObj[$this->sn]->ZRANGEBYSCORE($key, $star, $end);
  259. }
  260. /**
  261. * 返回名称为key的zset中元素member的score
  262. * @param $key
  263. * @param $member
  264. * @return string ,返回查询的member值
  265. */
  266. function zScore($key, $member)
  267. {
  268. return $this->redisObj[$this->sn]->ZSCORE($key, $member);
  269. }
  270. /*------------------------------------4.end sort set结构----------------------------------------------------*/
  271. /*------------------------------------5.hash结构----------------------------------------------------*/
  272. public function hSetJson($redis_key, $field, $data, $timeOut = 0)
  273. {
  274. $redis_info = json_encode($data); //field的数据value,以json的形式存储
  275. $re = $this->redisObj[$this->sn]->hSet($redis_key, $field, $redis_info);//存入缓存
  276. if ($timeOut > 0) $this->redisObj[$this->sn]->expire($redis_key, $timeOut);//设置过期时间
  277. return $re;
  278. }
  279. public function hGetJson($redis_key, $field)
  280. {
  281. $info = $this->redisObj[$this->sn]->hget($redis_key, $field);
  282. if ($info) {
  283. $info = json_decode($info, true);
  284. } else {
  285. $info = false;
  286. }
  287. return $info;
  288. }
  289. public function hSet($redis_key, $name, $data, $timeOut = 0)
  290. {
  291. $re = $this->redisObj[$this->sn]->hset($redis_key, $name, $data);
  292. if ($timeOut > 0) $this->redisObj[$this->sn]->expire($redis_key, $timeOut);
  293. return $re;
  294. }
  295. public function hSetNx($redis_key, $name, $data, $timeOut = 0)
  296. {
  297. $re = $this->redisObj[$this->sn]->hsetNx($redis_key, $name, $data);
  298. if ($timeOut > 0) $this->redisObj[$this->sn]->expire($redis_key, $timeOut);
  299. return $re;
  300. }
  301. /**
  302. * 增,普通逻辑的插入hash数据类型的值
  303. * @param $key ,键名
  304. * @param $data |array 一维数组,要存储的数据
  305. * @param $timeOut |num 过期时间
  306. * @return $number 返回OK【更新和插入操作都返回ok】
  307. */
  308. public function hMset($key, $data, $timeOut = 0)
  309. {
  310. $re = $this->redisObj[$this->sn]->hmset($key, $data);
  311. if ($timeOut > 0) $this->redisObj[$this->sn]->expire($key, $timeOut);
  312. return $re;
  313. }
  314. /**
  315. * 查,普通的获取值
  316. * @param $key ,表示该hash的下标值
  317. * @return array 。成功返回查询的数组信息,不存在信息返回false
  318. */
  319. public function hVals($key)
  320. {
  321. $re = $this->redisObj[$this->sn]->exists($key);//存在返回1,不存在返回0
  322. if (!$re) return false;
  323. $vals = $this->redisObj[$this->sn]->hvals($key);
  324. $keys = $this->redisObj[$this->sn]->hkeys($key);
  325. $re = array_combine($keys, $vals);
  326. foreach ($re as $k => $v) {
  327. if (!is_null(json_decode($v))) {
  328. $re[$k] = json_decode($v, true);//true表示把json返回成数组
  329. }
  330. }
  331. return $re;
  332. }
  333. /**
  334. *
  335. * @param $key
  336. * @param $filed
  337. * @return bool|string
  338. */
  339. public function hGet($key, $filed = [])
  340. {
  341. if (empty($filed)) {
  342. $re = $this->redisObj[$this->sn]->hgetAll($key);
  343. } elseif (is_string($filed)) {
  344. $re = $this->redisObj[$this->sn]->hget($key, $filed);
  345. } elseif (is_array($filed)) {
  346. $re = $this->redisObj[$this->sn]->hMget($key, $filed);
  347. }
  348. if (!$re) {
  349. return false;
  350. }
  351. return $re;
  352. }
  353. public function hDel($redis_key, $name)
  354. {
  355. $re = $this->redisObj[$this->sn]->hdel($redis_key, $name);
  356. return $re;
  357. }
  358. public function hLan($redis_key)
  359. {
  360. $re = $this->redisObj[$this->sn]->hLen($redis_key);
  361. return $re;
  362. }
  363. public function hIncre($redis_key, $filed, $value = 1)
  364. {
  365. return $this->redisObj[$this->sn]->hIncrBy($redis_key, $filed, $value);
  366. }
  367. /**
  368. * 检验某个键值是否存在
  369. * @param $keys keys
  370. * @param string $type 类型,默认为常规
  371. * @param string $field 若为hash类型,输入$field
  372. * @return bool
  373. */
  374. public function hExists($keys, $field = '')
  375. {
  376. $re = $this->redisObj[$this->sn]->hexists($keys, $field);//有返回1,无返回0
  377. return $re;
  378. }
  379. /*------------------------------------end hash结构----------------------------------------------------*/
  380. /*------------------------------------其他结构----------------------------------------------------*/
  381. /**
  382. * 设置自增,自减功能
  383. * @param $key ,要改变的键值
  384. * @param int $num ,改变的幅度,默认为1
  385. * @param string $member ,类型是zset或hash,需要在输入member或filed字段
  386. * @param string $type,类型,default为普通增减 ,还有:zset,hash
  387. * @return bool|int 成功返回自增后的scroll整数,失败返回false
  388. */
  389. public function incre($key, $num = 1, $member = '', $type = '')
  390. {
  391. $num = intval($num);
  392. switch (strtolower(trim($type))) {
  393. case "zset":
  394. $re = $this->redisObj[$this->sn]->zIncrBy($key, $num, $member);//增长权值
  395. break;
  396. case "hash":
  397. $re = $this->redisObj[$this->sn]->hincrby($key, $member, $num);//增长hashmap里的值
  398. break;
  399. default:
  400. if ($num > 0) {
  401. $re = $this->redisObj[$this->sn]->incrby($key, $num);//默认增长
  402. } else {
  403. $re = $this->redisObj[$this->sn]->decrBy($key, -$num);//默认增长
  404. }
  405. break;
  406. }
  407. if ($re) return $re;
  408. return false;
  409. }
  410. /**
  411. * 清除缓存
  412. * @param int $type 默认为0,清除当前数据库;1表示清除所有缓存
  413. */
  414. function flush($type = 0)
  415. {
  416. if ($type) {
  417. $this->redisObj[$this->sn]->flushAll();//清除所有数据库
  418. } else {
  419. $this->redisObj[$this->sn]->flushdb();//清除当前数据库
  420. }
  421. }
  422. /**
  423. * 检验某个键值是否存在
  424. * @param $keys keys
  425. * @param string $type 类型,默认为常规
  426. * @param string $field 若为hash类型,输入$field
  427. * @return bool
  428. */
  429. public function exists($keys, $type = '', $field = '')
  430. {
  431. switch (strtolower(trim($type))) {
  432. case 'hash':
  433. $re = $this->redisObj[$this->sn]->hexists($keys, $field);//有返回1,无返回0
  434. break;
  435. default:
  436. $re = $this->redisObj[$this->sn]->exists($keys);
  437. break;
  438. }
  439. return $re;
  440. }
  441. /**
  442. * 删除缓存
  443. * @param string|array $key 键值
  444. * @param $type 类型 默认为常规,还有hash,zset
  445. * @param string $field ,hash=>表示$field值,set=>表示value,zset=>表示value值,list类型特殊暂时不加
  446. * @return int | 返回删除的个数
  447. */
  448. public function delete($key, $type = "default", $field = '')
  449. {
  450. switch (strtolower(trim($type))) {
  451. case 'hash':
  452. $re = $this->redisObj[$this->sn]->hDel($key, $field);//返回删除个数
  453. break;
  454. case 'set':
  455. $re = $this->redisObj[$this->sn]->sRem($key, $field);//返回删除个数
  456. break;
  457. case 'zset':
  458. $re = $this->redisObj[$this->sn]->zDelete($key, $field);//返回删除个数
  459. break;
  460. default:
  461. $re = $this->redisObj[$this->sn]->del($key);//返回删除个数
  462. break;
  463. }
  464. return $re;
  465. }
  466. //日志记录
  467. public function logger($log_content, $position = 'user')
  468. {
  469. $max_size = 1000000; //声明日志的最大尺寸1000K
  470. $log_dir = './log';//日志存放根目录
  471. if (!file_exists($log_dir)) mkdir($log_dir, 0777);//如果不存在该文件夹,创建
  472. if ($position == 'user') {
  473. $log_filename = "{$log_dir}/User_redis_log.txt"; //日志名称
  474. } else {
  475. $log_filename = "{$log_dir}/Wap_redis_log.txt"; //日志名称
  476. }
  477. //如果文件存在并且大于了规定的最大尺寸就删除了
  478. if (file_exists($log_filename) && (abs(filesize($log_filename)) > $max_size)) {
  479. unlink($log_filename);
  480. }
  481. //写入日志,内容前加上时间, 后面加上换行, 以追加的方式写入
  482. file_put_contents($log_filename, date('Y-m-d_H:i:s') . " " . $log_content . "\n", FILE_APPEND);
  483. }
  484. function flushDB()
  485. {
  486. $this->redisObj[$this->sn]->flushDB();
  487. }
  488. function __destruct()
  489. {
  490. $this->redisObj[$this->sn]->close();
  491. }
  492. /**
  493. * 魔术方法 有不存在的操作的时候执行
  494. * @access public
  495. * @param string $method 方法名
  496. * @param array $args 参数
  497. * @return mixed
  498. */
  499. public function __call($method, $args)
  500. {
  501. call_user_func_array([$this->redisObj[$this->sn], $method], $args);
  502. }
  503. }