千家信息网

Redis和Lua实现分布式限流器

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,本篇文章为大家展示了Redis和Lua实现分布式限流器,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。原理计数器算法是指在一段窗口时间内允许通过的固定数量的请求
千家信息网最后更新 2026年11月01日Redis和Lua实现分布式限流器

本篇文章为大家展示了Redis和Lua实现分布式限流器,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

原理

计数器算法是指在一段窗口时间内允许通过的固定数量的请求, 比如10次/秒, 500次/30秒.

如果设置的时间粒度越细, 那么限流会更平滑.

实现

所使用的 Lua 脚本

-- 计数器限流-- 此处支持的最小单位时间是秒, 若将 expire 改成 pexpire 则可支持毫秒粒度.-- KEYS[1] string 限流的key-- ARGV[1] int  限流数-- ARGV[2] int  单位时间(秒)local cnt = tonumber(redis.call("incr", KEYS[1]))if (cnt == 1) then -- cnt 值为1说明之前不存在该值, 因此需要设置其过期时间 redis.call("expire", KEYS[1], tonumber(ARGV[2]))elseif (cnt > tonumber(ARGV[1])) then return -1end return cnt

返回 -1 表示超过限流, 否则返回当前单位时间已通过的请求数

key 可以但不限于以下的情况

  • ip + 接口

  • user_id + 接口

优点

  • 实现简单

缺点

  • 粒度不够细的情况下, 会出现在同一个窗口时间内出现双倍请求数

注意

  • 尽量保持时间粒度精细

场景分析

eg. 1000/3s 的限流

极端情况1:

第1秒请求数 10

第2秒请求数 10

第3秒请求数 980

第4秒请求数 900

第5秒请求数 100

第6秒请求数 0

此时注意第3~5秒内的总请求数高达 1980

极端情况2:

第1秒请求数 1000

第2秒请求数 0

第3秒请求数 0

此时后续的第2~3秒会出现大量拒绝请求

令牌桶模式

原理

令牌桶的

  1. 桶中保存有令牌, 存在上限, 且一开始是满的

  2. 每次请求都要消耗令牌(可根据不同请求消耗不同数量的令牌)

  3. 每隔一段时间(固定速率)会往桶中放令牌

桶的实现还分为:

可预消费

提前预支令牌数: 前人挖坑, 后人跳

不可预消费

令牌数不够直接拒绝

实现

此处实现的不可预消费的令牌桶, 具体Lua代码:

-- 令牌桶限流: 不支持预消费, 初始桶是满的-- KEYS[1] string 限流的key-- ARGV[1] int  桶最大容量-- ARGV[2] int  每次添加令牌数-- ARGV[3] int  令牌添加间隔(秒)-- ARGV[4] int  当前时间戳local bucket_capacity = tonumber(ARGV[1])local add_token = tonumber(ARGV[2])local add_interval = tonumber(ARGV[3])local now = tonumber(ARGV[4])-- 保存上一次更新桶的时间的keylocal LAST_TIME_KEY = KEYS[1].."_time";   -- 获取当前桶中令牌数local token_cnt = redis.call("get", KEYS[1]) -- 桶完全恢复需要的最大时长local reset_time = math.ceil(bucket_capacity / add_token) * add_interval;if token_cnt then -- 令牌桶存在 -- 上一次更新桶的时间 local last_time = redis.call('get', LAST_TIME_KEY) -- 恢复倍数 local multiple = math.floor((now - last_time) / add_interval) -- 恢复令牌数 local recovery_cnt = multiple * add_token -- 确保不超过桶容量 local token_cnt = math.min(bucket_capacity, token_cnt + recovery_cnt) - 1  if token_cnt < 0 then  return -1; end  -- 重新设置过期时间, 避免key过期 redis.call('set', KEYS[1], token_cnt, 'EX', reset_time)       redis.call('set', LAST_TIME_KEY, last_time + multiple * add_interval, 'EX', reset_time) return token_cnt else -- 令牌桶不存在 token_cnt = bucket_capacity - 1 -- 设置过期时间避免key一直存在 redis.call('set', KEYS[1], token_cnt, 'EX', reset_time); redis.call('set', LAST_TIME_KEY, now, 'EX', reset_time + 1);  return token_cnt end

令牌桶的关键是以下几个参数:

  • 桶最大容量

  • 每次放入的令牌数

  • 放入令牌的间隔时间

令牌桶的实现不会出现计数器模式中单位时间内双倍流量的问题.

上述内容就是Redis和Lua实现分布式限流器,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注行业资讯频道。

令牌 时间 单位 情况 粒度 消费 最大 容量 计数器 支持 分布式 限流器 不同 不够 内容 原理 双倍 技能 接口 数量 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技园 互联网科技名片 北京互联网科技公司 礼当家互联网科技 成都互联网科技公司 小马过河互联网科技 云电互联网科技 南京欣网互联网科技 伴你行互联网科技有限公司 互联网科技英文翻译 富国互联网科技创新基金 深圳市运趣互联网科技有限公司 金融科技与互联网金融相同和不同 来此购互联网科技有限公司 湖北码尼互联网科技有限公司电话 赶超互联网科技 微信多开 科技类公司包括互联网吗 浙南科技城互联网大厦建设工程 恒生互联网科技业指数调整周期 互联网科技股为什么大涨 保险科技 互联网保险 互联网科技公司经营范围 互联网金融与金融科技 济南华为互联网科技产业总部基地 互联网教育科技公司vipkid 佳云科技和互联网广告 河南猎农互联网科技有限公司 消费医药和互联网科技 互联网科技数字货币 互联网相关科技技术
0