Redis = $container->get(\Redis::class); $this->Key = $this->Key . $key; } /** * @param string $key * @param string ...$dynamic 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,初始化 if (strlen($reqNo) >= $length && substr($reqNo, 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(0.001); } 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(string $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); } public function zadd($score, $member) { $redis = $this->Redis; $key = $this->Key; return $redis->zadd($key, $score, $member); } public function zcard() { $redis = $this->Redis; $key = $this->Key; return $redis->zcard($key); } public function zrem($member) { $redis = $this->Redis; $key = $this->Key; return $redis->zrem($key, $member); } // 递增返回 public function zRange($start_score = 0, $end_score = -1) { $redis = $this->Redis; $key = $this->Key; return $redis->zrange($key, $start_score, $end_score); } // 递减返回 public function zRevRange($start_score = 0, $end_score = -1) { $redis = $this->Redis; $key = $this->Key; return $redis->zRevRange($key, $start_score, $end_score); } public function hSet($field, $value) { $redis = $this->Redis; $key = $this->Key; return $redis->hset($key, $field, $value); } public function hKeys() { $redis = $this->Redis; $key = $this->Key; return $redis->hkeys($key); } public function hGet($field) { $redis = $this->Redis; $key = $this->Key; return $redis->hget($key, $field); } public function hDel($field) { $redis = $this->Redis; $key = $this->Key; return $redis->hdel($key, $field); } public function incrby_expire($num,$second) { $redis = $this->Redis; $key = $this->Key; $count = $redis->incrby($key,$num); //设置过期时间 $redis->expire($key, $second); return $count; } }