使用 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;
相关推荐
fastjson_16 小时前
Spark 安装和使用
大数据·分布式·spark
spter。16 小时前
从一次关注到最终一致:Canal、Outbox 与 Kafka 如何解决关系链双写问题
分布式·kafka
MC丶科17 小时前
软考架构师90天冲刺|DAY38·第二阶段综合测试-分布式与云原生
分布式·云原生·架构·serverless·service_mesh·软考架构师
hm宋17 小时前
ZooKeeper 容灾切换免重启实践:域名化配置与客户端自动迁移
分布式·zookeeper·云原生
kruptos1 天前
分布式系统怎么“选主“?Raft 共识一次讲清
开发语言·分布式·php·共识算法
小智老师PMP1 天前
2026深度解析|PMP第八版与NPDP核心侧重点本质区别(管理类证书怎么选)
开发语言·分布式·算法·职场和发展·产品经理
会周易的程序员1 天前
5Draft(五帝)测试报告
服务器·c++·分布式·raft·共识算法·共识·算力服务器
想要打 Acm 的小周同学呀1 天前
Kafka消息队列出现挤压如何解决?
分布式·kafka
stark张宇2 天前
分布式事务最全图解(6种方案):从强一致的2PC到最终对账,彻底搞懂数据一致性
分布式·后端
会周易的程序员2 天前
5Draft使用说明书
服务器·c++·分布式·raft·共识