RedisUtil.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. <?php
  2. namespace app\utils;
  3. class RedisUtil
  4. {
  5. private $Key;
  6. protected $Redis;
  7. private static $instances = [];
  8. protected $options = [
  9. 'host' => '127.0.0.1',
  10. 'port' => 6379,
  11. 'password' => '',
  12. 'select' => 0,
  13. 'timeout' => 0,//
  14. 'expire' => 0,
  15. 'persistent' => false,
  16. 'prefix' => '',
  17. ];
  18. public function __construct(string $key)
  19. {
  20. // 判断是否有扩展(若是你的apache没reids扩展就会抛出这个异常)
  21. if (!extension_loaded('redis')) {
  22. throw new \BadFunctionCallException('not support: redis');
  23. }
  24. $this->options = config('redis');
  25. $func = $this->options['persistent'] ? 'pconnect' : 'connect';// 判断是否长链接
  26. $this->Redis = new \Redis();
  27. $redis = $this->Redis->$func($this->options['host'], $this->options['port'], $this->options['timeout']);
  28. if (!$redis) {
  29. throw new \BadFunctionCallException('connection fail: redis');
  30. }
  31. if ($this->options['password'] != '') {
  32. $this->Redis->auth($this->options['password']);
  33. }
  34. if (0 != $this->options['select']) {
  35. $this->Redis->select($this->options['select']);
  36. }
  37. $this->Key = $this->options['prefix'] . ':' . $key;
  38. }
  39. /**
  40. * @param string $key
  41. * @param string ...$dynamic key动态值拼接
  42. * @return RedisUtil|mixed
  43. * @throws \Exception
  44. */
  45. public static function getInstance(string $key, string ...$dynamic)
  46. {
  47. $dynamics = '';
  48. foreach ($dynamic as $k => $v) {
  49. if ($k == 0) {
  50. $dynamics .= $v;
  51. } else {
  52. $dynamics .= '_' . $v;
  53. }
  54. }
  55. $instanceName = uniqid();
  56. if (!isset(self::$instances[$instanceName])) {
  57. self::$instances[$instanceName] = new self($key . $dynamics);
  58. }
  59. return self::$instances[$instanceName];
  60. }
  61. /**
  62. * 生成唯一标识
  63. * @param int $length 生成长度
  64. * @return string
  65. */
  66. public function createNo(int $length = 5): string
  67. {
  68. $redis = $this->Redis;
  69. $key = $this->Key;
  70. //指定键值新增+1 并获取
  71. $reqNo = $redis->incr($key);
  72. //值长度已达到5位,且首位已为9,初始化
  73. if (strlen($reqNo) >= $length && substr($reqNo, 0, 1) == 9) {
  74. $redis->set($key, 1);
  75. $reqNo = 1;
  76. }
  77. if ($reqNo == 1) {
  78. //设置月末到期
  79. $expire = strtotime(date('Y-m', strtotime("+1 month")) . '-01 00:00:00') - time();
  80. $redis->expire($key, $expire);
  81. }
  82. return sprintf("%0{$length}d", $reqNo);
  83. }
  84. /**
  85. * 限制尝试次数 (设定时间内)
  86. * @param int $second 秒
  87. * @param int $Times 次数
  88. * @return false|int
  89. */
  90. public function tryTimes(int $second, int $Times = 5)
  91. {
  92. $redis = $this->Redis;
  93. $key = $this->Key;
  94. //指定键值新增+1 并获取
  95. $count = $redis->incr($key);
  96. if ($count > $Times) {
  97. return false;
  98. }
  99. //设置过期时间
  100. if ($count == 1) {
  101. $redis->expire($key, $second);
  102. }
  103. return (int)$count;
  104. }
  105. /**
  106. * 加锁
  107. * @param int $timeout 锁的过期时间
  108. * @return false|string
  109. */
  110. public function Lock(int $timeout = 10)
  111. {
  112. $redis = $this->Redis;
  113. $lockName = $this->Key;//锁的名字
  114. #获取唯一标识符
  115. $identifier = uniqid();
  116. #锁的过期时间
  117. $end = time() + $timeout;
  118. #循环获取锁
  119. while (time() < $end) {
  120. #查看$lockName是否被上锁,为$lockName设置过期时间,防止死锁
  121. if ($redis->set($lockName, $identifier, ['ex' => $timeout, 'nx'])) {
  122. return $identifier;
  123. }
  124. #停止0.001ms
  125. usleep(0.001);
  126. }
  127. return false;
  128. }
  129. /**
  130. * 释放锁
  131. * @param string $identifier 锁的唯一值
  132. * @return bool
  133. */
  134. public function releaseLock(string $identifier): bool
  135. {
  136. $redis = $this->Redis;
  137. $lockName = $this->Key;//锁的名字
  138. // 判断是锁有没有被其他客户端修改
  139. if ($redis->get($lockName) != $identifier) {
  140. #其他客户端修改了锁,不能删除别人的锁
  141. return false;
  142. }
  143. #释放锁
  144. $redis->del($lockName);
  145. return true;
  146. }
  147. public function setex($value, int $second)
  148. {
  149. $redis = $this->Redis;
  150. $key = $this->Key;
  151. return $redis->setex($key, $second, $value);
  152. }
  153. public function set($value, $options = null)
  154. {
  155. $redis = $this->Redis;
  156. $key = $this->Key;
  157. return $redis->set($key, $value, $options);
  158. }
  159. public function get()
  160. {
  161. $redis = $this->Redis;
  162. $key = $this->Key;
  163. return $redis->get($key);
  164. }
  165. public function del()
  166. {
  167. $redis = $this->Redis;
  168. $key = $this->Key;
  169. return $redis->del($key);
  170. }
  171. //加入list
  172. public function lPush($value)
  173. {
  174. $redis = $this->Redis;
  175. $key = $this->Key;
  176. return $redis->lPush($key, $value);
  177. }
  178. //删除右边
  179. public function rPop()
  180. {
  181. $redis = $this->Redis;
  182. $key = $this->Key;
  183. return $redis->rPop($key);
  184. }
  185. public function rPush($value)
  186. {
  187. $redis = $this->Redis;
  188. $key = $this->Key;
  189. return $redis->rPush($key, $value);
  190. }
  191. public function lPopLine($num)
  192. {
  193. $redis = $this->Redis;
  194. $key = $this->Key;
  195. $pipe = $redis->multi(\Redis::PIPELINE);
  196. $pipe->lRange($key, 0, $num - 1);
  197. $pipe->lTrim($key, $num, -1);
  198. return $pipe->exec();
  199. }
  200. //list长度
  201. public function lLen()
  202. {
  203. $redis = $this->Redis;
  204. $key = $this->Key;
  205. return $redis->llen($key);
  206. }
  207. public function zadd($score, $member)
  208. {
  209. $redis = $this->Redis;
  210. $key = $this->Key;
  211. return $redis->zadd($key, $score, $member);
  212. }
  213. public function zcard()
  214. {
  215. $redis = $this->Redis;
  216. $key = $this->Key;
  217. return $redis->zcard($key);
  218. }
  219. public function zrem($member)
  220. {
  221. $redis = $this->Redis;
  222. $key = $this->Key;
  223. return $redis->zrem($key, $member);
  224. }
  225. // 递增返回
  226. public function zRange($start_score = 0, $end_score = -1, $options = null)
  227. {
  228. $redis = $this->Redis;
  229. $key = $this->Key;
  230. return $redis->zrange($key, $start_score, $end_score,$options);
  231. }
  232. // 递减返回
  233. public function zRevRange($start_score = 0, $end_score = -1, $options = null)
  234. {
  235. $redis = $this->Redis;
  236. $key = $this->Key;
  237. return $redis->zRevRange($key, $start_score, $end_score,$options);
  238. }
  239. public function zRevRank($start, $end, $scores = null)
  240. {
  241. $redis = $this->Redis;
  242. $key = $this->Key;
  243. return $redis->zRevRange($key, $start, $end,$scores);
  244. }
  245. public function zRank($member)
  246. {
  247. $redis = $this->Redis;
  248. $key = $this->Key;
  249. return $redis->zRank($key, $member);
  250. }
  251. public function zUnionStore($output, $zSetKeys, ?array $weights = null, $aggregateFunction = null)
  252. {
  253. $redis = $this->Redis;
  254. return $redis->zUnionStore($output, $zSetKeys, $weights, $aggregateFunction);
  255. }
  256. public function hSet($field, $value)
  257. {
  258. $redis = $this->Redis;
  259. $key = $this->Key;
  260. return $redis->hset($key, $field, $value);
  261. }
  262. public function hKeys()
  263. {
  264. $redis = $this->Redis;
  265. $key = $this->Key;
  266. return $redis->hkeys($key);
  267. }
  268. public function hGet($field)
  269. {
  270. $redis = $this->Redis;
  271. $key = $this->Key;
  272. return $redis->hget($key, $field);
  273. }
  274. public function hDel($field)
  275. {
  276. $redis = $this->Redis;
  277. $key = $this->Key;
  278. return $redis->hdel($key, $field);
  279. }
  280. public function hGetAll()
  281. {
  282. $redis = $this->Redis;
  283. $key = $this->Key;
  284. return $redis->hGetAll($key);
  285. }
  286. }