<?php
namespace App\Traits;
use App\Exceptions\BusinessException;
use Illuminate\Support\Facades\Redis;
trait RedisLimiter
{
/**
* 限流
* @param $key
* @param $limit
* @param $expire_time
* @return bool
* @throws BusinessException
* @author wzx 2023/4/25 17:35
*/
public static function set($key, $limit, $expire_time)
{
$current_time = time();
$result = Redis::eval(self::lua(), 1, $key, $limit, $expire_time, $current_time);
if ($result == 0) {
throw new BusinessException([-1, '請求頻繁']);
}
return true;
}
private static function lua(): string
{
return <<<LUA
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local expire_time = tonumber(ARGV[2])
local current_time = tonumber(ARGV[3])
local count = redis.call('get', key)
if count and tonumber(count) >= limit then
return 0
else
redis.call('incr', key)
redis.call('expire', key, expire_time)
return 1
end
LUA;
}
}
使用
$key = "user:xxx" . $user_id;
// 一分鐘請求1次
RedisLimiter::set($key, 1, 60);
本作品採用《CC 協議》,轉載必須註明作者和本文連結