使用 sorted set 实现令牌桶限流

业务场景为限制消息发送,要求每天不超过一次,每七天不超过三次

Redission 的 RRateLimiter 虽然功能完备且支持自定义限流配置,但是每个限流器都需要维护三个 key,并且 lua 脚本中的判断逻辑较为复杂。

见:Redisson 分布式限流器 RRateLimiter 的使用及原理

此外,本业务场景每次固定只需要获取一个令牌,且时间等限流参数固定,因此完全可以通过一个 sorted set 实现令牌桶限流。

对应 lua 脚本:

lua 复制代码
-- sorted set 令牌桶的 key 
local key = KEYS[1];
-- 当前日期 格式为 yyyy-MM-dd
local member = ARGV[1];
-- 当前日期 0 点对应的时间戳 单位为秒
local timestamp = tonumber(ARGV[2]);

local exists = redis.call('exists', key);
if exists == 0 then
    -- 创建并授权
    redis.call('zadd', key, timestamp, member);
    redis.call('expire', key, 7 * 24 * 60 * 60);
    return 1;
else
    -- 移除七天前的授权记录 本质是回收令牌
    local sevenDaysAgo = timestamp - 7 * 24 * 60 * 60;
    redis.call('zremrangebyscore', key, '-inf', sevenDaysAgo);
    
    -- 如果队列长度少于 3 则尝试进行授权
    local length = redis.call('zcard', key);
    if length < 3 then
        local count = redis.call('zcount', key, timestamp, timestamp);
        if (count == 0) then
            -- 每天不超过一次
            redis.call('zadd', key, timestamp, member);
            redis.call('expire', key, 7 * 24 * 60 * 60);
            return 1;
        else
            return 0;
        end;
    else
        return 0;
    end;
end;
相关推荐
KANGBboy10 小时前
doris+kafka安装部署(单机+集群)二时钟服务器 java_home
服务器·分布式
爱笑的k1112 小时前
分布式通信原语
分布式·ai infra
实战派K8S&DB12 小时前
GaussDB 高可用演进:从流复制到 DCF 分布式共识
分布式·gaussdb
写后端的胖头鱼12 小时前
【高频面试题】分布式锁在项目中的应用
java·分布式·后端·分布式锁·高频面试题
clz131452113 小时前
Kafka 日消 10 亿场景:用 ConcurrentLinkedQueue 实现高性能批量消费缓冲
分布式·kafka·linq
隐擎fox1 天前
高性能网络爬虫架构设计:基于 Python 的长连接复用与分布式会话池调度实践
分布式·python·网络协议·tcp/ip·高并发·网络爬虫、
闲云自留地1 天前
云平台存储管理员:Cinder 创建挂载卷 + Swift 分布式存储原理
分布式·wpf·swift
橙子圆1231 天前
RabbitMQ知识1
分布式·rabbitmq
clz13145211 天前
风险特征系统 EPC 子系统:基于 Kafka 数据源与数据集配置的 Flink 指标清洗加工
分布式·flink·kafka