使用 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;
相关推荐
电气铺二表姐13774416615几秒前
微电网管理系统:赋能分布式能源高效运行,筑牢园区/工业能源安全防线
分布式·能源
回家路上绕了弯5 分钟前
分布式系统设计:中心化与去中心化思想的碰撞与融合
分布式·后端
yeshihouhou8 分钟前
redis实现分布式锁
redis·分布式·junit
song50120 分钟前
鸿蒙 Flutter 语音交互进阶:TTS/STT 全离线部署与多语言适配
分布式·flutter·百度·华为·重构·electron·交互
weixin_4424722211 小时前
12A高效同步降压转换器在便携设备、网络系统与分布式电源中与汽车电子工业控制的WD5030K应用与设计指南
分布式·汽车·工业控制·电路设计·同步降压·12a·qfn5x5
嘻哈baby2 小时前
分布式组网架构设计:从BitTorrent DHT到现代SD-WAN的演进
分布式·后端·asp.net
小雨下雨的雨2 小时前
第9篇:Redis分布式锁与分布式ID
redis·分布式
赵得C2 小时前
软件设计师进阶知识点解析:分布式与数据应用考点精讲
java·开发语言·分布式·设计模式
500842 小时前
鸿蒙 Flutter 分布式数据同步:DistributedData 实时协同实战
分布式·flutter·华为·electron·开源·wpf·音视频
song5012 小时前
鸿蒙 Flutter 图像编辑:原生图像处理与滤镜开发
图像处理·人工智能·分布式·flutter·华为·交互