Redis = $container->get(\Redis::class); $this->Key = $key; } /** * @param string $key * @param string ...$dynamic key动态值拼接 示例 RedisUtil::getInstance('key','user_no'); 则代表着 用户编号唯一的key * @return RedisUtil|mixed * @throws \Exception */ public static function getInstance(string $key, string ...$dynamic) { $dynamics = ''; foreach ($dynamic as $k => $v) { if ($k == 0) { $dynamics .= $v; } else { $dynamics .= '_' . $v; } } $instanceName = Coroutine::id() . uniqid();//协程id&唯一id组成 if (!isset(self::$instances[$instanceName])) { self::$instances[$instanceName] = new self($key . $dynamics); Coroutine::defer(function () use ($instanceName) { unset(self::$instances[$instanceName]); }); } return self::$instances[$instanceName]; } /** * 生成唯一标识 * @param int $length 生成长度 * @return string */ public function createNo(int $length = 5): string { $redis = $this->Redis; $key = $this->Key; //指定键值新增+1 并获取 $reqNo = $redis->incr($key); //值长度已达到5位,且首位已为9,初始化 $reqNoString = (string)$reqNo; if (strlen($reqNoString) >= $length && substr($reqNoString, 0, 1) == 9) { $redis->set($key, 1); $reqNo = 1; } if ($reqNo == 1) { //设置月末到期 $expire = strtotime(date('Y-m', strtotime("+1 month")) . '-01 00:00:00') - time(); $redis->expire($key, $expire); } return sprintf("%0{$length}d", $reqNo); } /** * 限制接口请求次数 * @param string $path 可以是路由,可以是地址,可以是ip,总之是 string 即可 * @param int $second 秒 * @param int $count 多长时间内限制请求次数 * @return bool */ public function requestLimit(string $path, int $second, int $count): bool { $redis = $this->Redis; $key = $this->Key . md5($path); /*$_cou = $redis->incr($key); if ($_cou > $count) return false; if ($_cou == 1) $redis->expire($key, $second); unset($redis, $_cou); return true;*/ $luaScript = << tonumber(ARGV[1]) then return 0 end return 1 lua; return (bool)$redis->eval($luaScript, [$key, $count, $second], 1); } /** * 限制尝试次数 (设定时间内) * @param int $second 秒 * @param int $Times 次数 * @return false|int */ public function tryTimes(int $second, int $Times = 5) { $redis = $this->Redis; $key = $this->Key; //指定键值新增+1 并获取 $count = $redis->incr($key); if ($count > $Times) { return false; } //设置过期时间 if ($count == 1) { $redis->expire($key, $second); } return (int)$count; } /** * 加锁 * @param int $timeout 锁的过期时间 * @return false|string */ public function Lock(int $timeout = 3) { $redis = $this->Redis; $lockName = $this->Key;//锁的名字 #获取唯一标识符 $identifier = uniqid(); #锁的过期时间 $end = time() + $timeout; #循环获取锁 while (time() < $end) { #查看$lockName是否被上锁,为$lockName设置过期时间,防止死锁 if ($redis->set($lockName, $identifier, ['ex' => $timeout, 'nx'])) { return $identifier; } #停止0.001ms usleep(1); } return false; } /** * 释放锁 * @param string $identifier 锁的唯一值 * @return bool */ public function releaseLock(string $identifier): bool { $redis = $this->Redis; $lockName = $this->Key;//锁的名字 // 判断是锁有没有被其他客户端修改 if ($redis->get($lockName) != $identifier) { #其他客户端修改了锁,不能删除别人的锁 return false; } #释放锁 $redis->del($lockName); return true; } public function setex(mixed $value, int $second) { $redis = $this->Redis; $key = $this->Key; return $redis->setex($key, $second, $value); } public function get() { $redis = $this->Redis; $key = $this->Key; return $redis->get($key); } public function del() { $redis = $this->Redis; $key = $this->Key; return $redis->del($key); } //加入list public function lPush(array $value) { $redis = $this->Redis; $key = $this->Key; return $redis->lPush($key, $value); } //删除右边 public function rPop() { $redis = $this->Redis; $key = $this->Key; return $redis->rPop($key); } //list长度 public function lLen() { $redis = $this->Redis; $key = $this->Key; return $redis->llen($key); } //删,移除有序集key中的一个或多个成员,不存在的成员将被忽略。[del_num | 0] public function zRem($member) { $redis = $this->Redis; $key = $this->Key; return $redis->zRem($key,$member); } // 增加分数 public function zIncrBy($value,$member) { $redis = $this->Redis; $key = $this->Key; return $redis->zIncrBy($key, $value, $member); } //查,通过(score从大到小)【排序名次范围】拿member值,返回有序集key中,【指定区间内】的成员 [array | null] public function zRevRange(int $start, int $end, mixed $scores = null) { $redis = $this->Redis; $key = $this->Key; return $redis->zRevRange($key, $start, $end, $scores); } public function zRevRank(mixed $member) { $redis = $this->Redis; $key = $this->Key; return $redis->zRevRank($key, $member); } //查,取值【value|false】 public function hGet($member) { $redis = $this->Redis; $key = $this->Key; return $redis->hGet($key,$member); } //删,删除指定下标的field,不存在的域将被忽略,[num | false] public function hDel($field) { $redis = $this->Redis; $key = $this->Key; return $redis->hDel($key,$field); } //增,改,将哈希表key中的域field的值设为value,不存在创建,存在就覆盖【1 | 0】 public function hSet($member,$value) { $redis = $this->Redis; $key = $this->Key; return $redis->hSet($key,$member,$value); } //增,改,将一个或多个member元素及其score值加入到有序集key当中。[num | 0] public function zAdd($score, $member) { $redis = $this->Redis; $key = $this->Key; return $redis->zAdd($key,$score,$member); } }