Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测)

Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测)

本文是能直接落地 的一篇:讲清算法差异,给出可复用的 Lua 脚本 & Node/Python 调用示例,并教你做可靠消费、重试、监控与容量估算。文末提供可下载脚本包与压测脚本。

### 文章目录

  • [Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测)](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [@[toc]](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [1. 选型速览(什么时候用哪种)](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [2. 固定窗口限流(Fixed Window)](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [3. 滑动窗口限流(Sliding Window)](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [4. 延时队列(ZSet 版)](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [5. Streams 消费组(可靠消费)](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [6. 可靠性与重试策略(强烈建议照搬)](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [7. 监控与报警](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [8. 容量估算(算清楚再上)](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [8.1 滑动窗口(ZSet)内存](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [8.2 ZSet 延时队列](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [8.3 Streams](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [9. 压测方法与参考脚本](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [9.1 一键启动](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [9.2 固定/滑动窗口压测(Node)](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [9.3 延时队列吞吐压测(ZSet)](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [10. 最佳实践清单(上线前逐条勾)](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [11. 附:完整脚本与基准工具包(可直接用)](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)
  • [12. 小结](#文章目录 Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测) @[toc] 1. 选型速览(什么时候用哪种) 2. 固定窗口限流(Fixed Window) 3. 滑动窗口限流(Sliding Window) 4. 延时队列(ZSet 版) 5. Streams 消费组(可靠消费) 6. 可靠性与重试策略(强烈建议照搬) 7. 监控与报警 8. 容量估算(算清楚再上) 8.1 滑动窗口(ZSet)内存 8.2 ZSet 延时队列 8.3 Streams 9. 压测方法与参考脚本 9.1 一键启动 9.2 固定/滑动窗口压测(Node) 9.3 延时队列吞吐压测(ZSet) 10. 最佳实践清单(上线前逐条勾) 11. 附:完整脚本与基准工具包(可直接用) 12. 小结)

1. 选型速览(什么时候用哪种)

场景 推荐 说明
API 限流,按用户/令牌/接口,每分钟 N 次 固定窗口(Fixed Window) 简单高效;边界时刻有突刺(burst)
更平滑、按任意滑动窗口统计 滑动窗口(Sliding Window,ZSet/Lua) 精确统计,写放大;适合高价值接口
服务端排队、定时任务按时间触发 ZSet 延时队列 score=readyAt,配合原子 claim/ack
多消费者、可靠消费与重投 Streams 消费组 自带 PEL/ack/reclaim,近似 MQ

2. 固定窗口限流(Fixed Window)

思想 :某个维度(如 uid)在窗口期 t 内计数,超过阈值拒绝。

Lua(原子)

lua 复制代码
-- KEYS[1]=key  ARGV[1]=limit  ARGV[2]=windowSec
local c = redis.call('INCR', KEYS[1])
if c == 1 then redis.call('EXPIRE', KEYS[1], ARGV[2]) end
if c > tonumber(ARGV[1]) then
  return {0, c, redis.call('PTTL', KEYS[1])}  -- {允许?, 当前计数, 剩余TTL(ms)}
else
  return {1, c, redis.call('PTTL', KEYS[1])}
end

Node.js 调用示例(ioredis)

js 复制代码
import fs from 'node:fs'
import Redis from 'ioredis'
const r = new Redis(process.env.REDIS_URL)
const sha = await r.script('load', fs.readFileSync('rate_limit_fixed.lua','utf8'))

const key = `rl:uid:${uid}:60`
const [ok, count, ttl] = await r.evalsha(sha, 1, key, 100, 60)
if (!ok) throw new Error('Too Many Requests')

优缺点

  • ✅ 极快、占用小;
  • ⚠️ 窗口边界可能出现"59s 内 0 次 + 1s 内 100 次"的突刺(可接受则用它)。

3. 滑动窗口限流(Sliding Window)

思想 :用 ZSet 存最近 t 内的时间戳,实时淘汰过期项;当前元素数即窗口内请求数。

Lua(精确滑窗)

lua 复制代码
-- KEYS[1]=zset; ARGV: now(ms), window(ms), limit, memberId(unique)
local now = tonumber(ARGV[1]); local win = tonumber(ARGV[2]); local limit = tonumber(ARGV[3])
redis.call('ZREMRANGEBYSCORE', KEYS[1], 0, now - win)
local count = redis.call('ZCARD', KEYS[1])
if count >= limit then
  local ttl = redis.call('PTTL', KEYS[1]); if ttl < 0 then redis.call('PEXPIRE', KEYS[1], win) end
  return {0, count, ttl}
end
redis.call('ZADD', KEYS[1], now, ARGV[4]); redis.call('PEXPIRE', KEYS[1], win)
return {1, count + 1, win}

何时选它

  • 金融/库存等高价值接口
  • 需要"随时点 往前 t 秒都不超过 N 次"的严格语义。

成本提示 :每次写 1 个元素,并维护 ZSet;高 QPS 下注意内存(见 §8)。


4. 延时队列(ZSet 版)

生产者ZADD delayQ <readyAtMillis> jobJSON
消费者循环

  1. 原子claim :把 score <= now 的任务移动processing,设置可见期(visibility timeout);
  2. 处理成功 ACK;失败或超时由requeue脚本放回。

Lua 片段(claim/ack/requeue)

lua 复制代码
-- claim: KEYS[1]=ready, KEYS[2]=processing; ARGV[1]=now, ARGV[2]=limit, ARGV[3]=processingTTLms
-- 返回被领取的 job 列表(字符串)
-- ack:   KEYS[1]=processing; ARGV[1]=job  -> ZREM
-- requeue_expired: KEYS[1]=processing, KEYS[2]=ready; ARGV[1]=now

特性

  • ✅ 简单、可做延迟/重试退避(把 score 往后推);
  • ⚠️ 需要自己维护可见期幂等(见下一节)。

5. Streams 消费组(可靠消费)

概念XADD 写入;XGROUP 创建消费组;消费者 XREADGROUP GROUP g c ... 读取,处理后 XACK。未确认消息记录在 Pending Entries List (PEL) 中,可用 XCLAIM 抢回超时消息。

最小流程

bash 复制代码
XADD order:stream * orderId 1001 status CREATED
XGROUP CREATE order:stream g1 $ MKSTREAM
XREADGROUP GROUP g1 c1 COUNT 10 BLOCK 5000 STREAMS order:stream >
XACK order:stream g1 1692340123-0
XPENDING order:stream g1            # 看积压
XCLAIM order:stream g1 c2 60000 1692340123-0  # 抢回超时消息

适用 :需要至少一次 消费、可重放/补偿的队列场景;天然多消费者与追踪"未确认"。


6. 可靠性与重试策略(强烈建议照搬)

  1. 幂等 :业务侧必须可重试(订单号/请求号唯一);Redis 脚本只保证原子性,不保证业务 Exactly-once。
  2. 可见期 :ZSet 队列设置 processingTTL;Streams 用 XREADGROUP + XACK + XCLAIM
  3. 退避重试 :指数退避 backoff = min(base*2^retry, max),超过 maxRetry 进入 DLQ
  4. 监控阈值
    • ZSet:ZCARD(delayQ)ZCARD(processing)
    • Streams:XLENXPENDING、各消费者 idle 时间;
    • 限流:允许/拒绝比(命中率)、拒绝分布。

7. 监控与报警

  • INFO stats|memory|keyspaceinstantaneous_ops_per_sec、内存、命中率;
  • 慢脚本:SLOWLOG,Lua 不要执行耗时 I/O;
  • Prometheus Exporter :抓 redis_exporter 指标;自定义业务指标(允许/拒绝/重试次数)写 Prom
  • 仪表盘建议
    • 限流:allow_rateblock_ratep50/p99 延迟
    • 队列:ready_len / processing_len / XPENDINGack 率requeue 率
    • 容量:used_memoryevicted_keyshit_ratio

8. 容量估算(算清楚再上)

8.1 滑动窗口(ZSet)内存

  • 每个请求写入一条 ZSet 记录;估算:
    Mem ≈ 用户数 * (QPS_user * 窗口秒) * bytes_per_entry
  • bytes_per_entry 依 value 长度而定,50--120B 粗估(含元数据)。
  • 例:2 万用户高峰每人 5 QPS、窗口 60s → 2e45 60=6e6 条 → 约 6e6*100B ≈ 600MB

8.2 ZSet 延时队列

  • ready + processing 的元素个数近似为待处理任务 + 正在处理任务;按 payload 大小估计。
  • 控制保留:处理完成后删除/归档;或保留最近 N 分钟做幂等对照。

8.3 Streams

  • 使用 XTRIM MAXLEN ~ N 控制长度:
    XTRIM order:stream MAXLEN ~ 1e6(近似裁剪,开销更低)。
  • 单条大小≈字段名+值长度;payload 建议压缩或用字段化结构。

9. 压测方法与参考脚本

9.1 一键启动

bash 复制代码
docker run -d --name redis -p 6379:6379 redis:7

9.2 固定/滑动窗口压测(Node)

bash 复制代码
# 需要脚本:rate_limit_fixed.lua / rate_limit_sliding.lua + ioredis
node bench_fixed.js
node bench_sliding.js
# 输出示例(JSON):{ "algo": "fixed", "allowed": 10000, "blocked": 10000, "ms": 320 }

9.3 延时队列吞吐压测(ZSet)

bash 复制代码
node bench_delayq.js
# 输出示例:{ "delayq":"zset","tasks":10000,"workers":8,"ms":1450 }

观察指标:整体耗时、每秒处理数、CPU 占用、Redis 慢日志、ready/processing 长度变化。


10. 最佳实践清单(上线前逐条勾)

  • 限流 key 规范:rl:<algo>:<dim>:<id>;随机TTL 抖动防同刻雪崩。
  • Lua 返回结构明确,错误码与剩余 TTL都给到。
  • 队列消费幂等 :业务层唯一键/去重表;失败 N 次入 DLQ 并告警。
  • Streams 开启最小空闲时间XCLAIM ... MINIDLE),定时 XPENDING/XINFO 巡检。
  • 监控就绪:Prometheus + Grafana;关键指标报警。
  • 容量评估 + 压测通过,内存上限 maxmemory 与淘汰策略已配置。
  • 预案:Redis 宕机/主从切换时的限流降级队列积压处理策略。

11. 附:完整脚本与基准工具包(可直接用)

我已把文中用到的 Lua 脚本 + Node 基准脚本 + Docker Compose 打成一个可下载工具包:

下载: redis-rlq-toolkit.zip(CSDN下载)

包含:rate_limit_fixed.luarate_limit_sliding.luadelayq_claim/ack/requeue.luabench_fixed/bench_sliding/bench_delayq.jsdocker-compose.yml 与 README。解压后按 README 即可跑通。


12. 小结

  • 限流:固定窗口够快、滑动窗口够准;二者按接口价值取舍。
  • 队列:延时需求用 ZSet 简洁好用;需要可靠消费与重投,用 Streams 消费组更稳。
  • 工程化:幂等、可见期、退避与监控缺一不可;上生产前把容量和压测做扎实。
相关推荐
利来利往3 小时前
【ai写代码】lua-判断表是否被修改
lua
Warren983 小时前
Lua 脚本在 Redis 中的应用
java·前端·网络·vue.js·redis·junit·lua
xiao-xiang3 小时前
redis-保姆级配置详解
数据库·redis
xiao-xiang9 小时前
redis-sentinel基础概念及部署
数据库·redis·sentinel
云间月13149 小时前
飞算JavaAI:从智能调度到出行服务的全链路技术升级
java·redis·飞算javaai炫技赛
柏油10 小时前
Spring @Cacheable 解读
redis·后端·spring
Runing_WoNiu16 小时前
Redis核心架构
数据库·redis·架构
编程(变成)小辣鸡18 小时前
Redis 知识点与应用场景
数据库·redis·缓存
菜鸟康1 天前
Redis7学习--事务
redis