当前位置: 首页 > news >正文

Redis Lua脚本实现令牌桶限流算法

脚本代码
-- 参数说明:
-- KEYS[1]: 令牌桶的Key(如 rate_limit:api1)
-- ARGV[1]: 令牌桶容量(最大令牌数)
-- ARGV[2]: 令牌生成速率(每秒生成数)
-- ARGV[3]: 当前时间戳(秒)
-- ARGV[4]: 请求令牌数(通常为1)

local key = KEYS[1]
local capacity = tonumber(ARGV[1])
local rate = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
local requested = tonumber(ARGV[4])

-- 1. 获取桶内当前状态
local data = redis.call("HMGET", key, "tokens", "last_refill_time")
local tokens = tonumber(data[1]) or capacity  -- 初始化为满桶
local last_refill = tonumber(data[2]) or now

-- 2. 计算时间差并生成新令牌
local delta = math.max(now - last_refill, 0)
local new_tokens = math.floor(delta * rate)
tokens = math.min(tokens + new_tokens, capacity)  -- 不超过桶容量

-- 3. 更新最后一次补充时间(仅在生成新令牌时更新)
if new_tokens > 0 then
    redis.call("HSET", key, "last_refill_time", now)
end

-- 4. 判断是否有足够令牌
local result = 0
if tokens >= requested then
    tokens = tokens - requested
    result = 1  -- 允许请求
    redis.call("HSET", key, "tokens", tokens)
else
    -- 令牌不足,保留当前令牌数
    redis.call("HSET", key, "tokens", tokens)
end

-- 5. 设置Key过期时间(避免冷数据占用内存)
redis.call("EXPIRE", key, math.ceil(capacity / rate) * 2)

return {result, tokens}  -- 返回是否允许和剩余令牌数

脚本逐行解析

  1. 参数接收

    • ​KEYS[1]​:标识不同限流目标的唯一Key(如按API路径 + 用户ID)。
    • ​ARGV​:传递容量、速率、当前时间戳和请求令牌数。
  2. 初始化桶状态

    • 使用 HMGET​ 获取当前令牌数(tokens​)和最后一次补充时间(last_refill_time​)。
    • 若首次访问,默认令牌桶为满容量(tokens = capacity​)。
  3. 令牌补充逻辑

    • 计算自上次补充以来的时间差(delta​),生成新令牌数 new_tokens = delta * rate​。
    • 确保令牌总数不超过桶容量(math.min​)。
  4. 令牌消费判断

    • 若剩余令牌足够,扣除请求数并返回允许(result = 1​)。
    • 若不足,保留当前令牌数(突发后可能需要时间恢复)。
  5. 过期时间设置

    • 根据容量和速率计算合理TTL(如容量10,速率5/秒,TTL=4秒),避免内存泄漏。

      指令牌长时间没人拿然后一直占用内存

相关文章:

  • leetcode-27 移除元素(基础算法—双指针)
  • 【Node.js入门笔记9---path 模块】
  • 上海蒂正科技有限公司:技术驱动数字化,打造高端企业门户新标杆
  • 数组模拟邻接表 #图论
  • 递归陷阱:如何优雅地等待 props.parentRoute?
  • 使用Java实现Oracle表结构转换为PostgreSQL的示例方案(AI)
  • 前端对接生成式AI接口(类ChatGPT)问题汇总
  • MySQL-sql优化
  • 网络运维学习笔记(DeepSeek优化版) 021 HCIA-Datacom新增知识点03园区网典型组网架构及案例实战
  • 【Hbase】查看所有表
  • EMC整改案例:某网络机顶盒网口辐射
  • java-正则表达式-集合-泛型-注解-异常
  • 0-组合优化图神经网络的退火机器辅助学习(arxiv 25)(完)
  • 在 Windows 系统下,将 FFmpeg 编译为 .so 文件
  • Linux下JDK1.8安装配置
  • 家族族谱管理系统基于Spring Boot
  • 快速查询手机是否处于联网状态?
  • 【SpringMVC】SpringMVC进阶,类型转换器源码分析,json转换,视图解析器,以及操作各种域的API
  • 遨游科普|三防平板是什么?哪些领域能用到?
  • 82.RadioButton的选中处理逻辑 C#例子 WPF例子
  • A股三大股指集体高开
  • 撤制镇如何突破困境?欢迎订阅《澎湃城市报告》第23期
  • 多地再发网约车从业及投资风险提示:避免盲目花费大笔资金“购车”入行
  • 游戏论|暴君无道,吊民伐罪——《苏丹的游戏》中的政治
  • 总粉丝破亿!当网络大V遇见硬核科技,互联网时代如何书写上海故事?
  • 牛市早报|国家发改委:今年将推出约3万亿元优质项目,支持民营企业参与