123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- <?php
- declare(strict_types=1);
- namespace App\Utils;
- use Hyperf\Context\ApplicationContext;
- use Hyperf\Coroutine\Coroutine;
- /**
- * 全局redis键值配置
- */
- class RedisUtil
- {
- /**
- * 设置redis key
- *
- * @var string
- */
- private string $Key;
- private $Redis;
- private static $instances = [];
- /**
- * @param string $key
- * @throws \Psr\Container\ContainerExceptionInterface
- * @throws \Psr\Container\NotFoundExceptionInterface
- */
- public function __construct(string $key)
- {
- $container = ApplicationContext::getContainer();
- $this->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 = <<<lua
- local count = redis.call("incr",KEYS[1])
- if count == 1 then
- redis.call('expire',KEYS[1],ARGV[2])
- end
- if count > 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);
- }
- }
|