`Laravel`版`小丑路人社区`改版中,与`Hyperf版小丑路人社区`数据互动,此版本改版中……尚未彻底完结!

Q:

redis 通过计数器限流

class RedisRateLimit
{
    protected static function getRedis()
    {
        return 'Redis的实例';
    }

    public static function throttle($key, int $minute = 1, int $max = 100)
    {
        // 获取Redis实例
        $redis = self::getRedis();
        // 毫秒时间戳
        $msectime = self::msectime();
        // 使用管道提升性能
        $pipe = $redis->multi($redis::PIPELINE);
        // vaule 与 score 使用毫秒时间戳
        $pipe->zadd($key, $msectime, $msectime);

        // 删除时间窗口之前的历史记录
        $pipe->zRemRangeByScore($key, 0, $msectime - $minute * 60 * 1000);

        // 获取当前时间窗口内所有的总数
        $pipe->zcard($key);
        // 多1秒过期时间
        $pipe->expire($key, $minute * 60 + 1);

        $replies = $pipe->exec();

        return $replies[2] > $max ? true : false;
    }

    //返回当前的毫秒时间戳
    static function msectime() {
        list($msec, $sec) = explode(' ', microtime());
        $msectime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
        return $msectime;
    }
}

示例

$key = 'route_001';

for ($i=0; $i < 10; $i++) {
    usleep(rand(200, 900));

    // 在一分钟内执行三次返回false,第四次及更多时,则为true
    var_dump(RedisRateLimit::throttle($key, 1, 3));
}
输出
bool(false)
bool(false)
bool(false)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
PHP
订阅

评论记录


评论/回复