首页/数据/Redis 进阶速查/滑动窗口限流:ZSet 加 Lua
本包目录(421 条)
数据结构与选型42 条
持久化56 条主从与哨兵51 条Cluster 集群44 条内存与管理99 条性能与排障129 条

滑动窗口限流:ZSet 加 Lua

把请求时间戳作为 ZSet 分数:Lua 内先删除窗口外记录、再统计数量、未超限才写入并返回;整套动作原子完成,避免并发下的计数偏差。

Redis 进阶速查数据更新于 2026-10-12
结构key 为限流对象,score 为毫秒时间戳
窗口如 60 秒内允许 100 次
原子Lua 内 ZREMRANGEBYSCORE 加 ZCARD 加 ZADD 加 PEXPIRE

Lua 脚本示意

Lua 脚本示意
local now = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local limit = tonumber(ARGV[3])
redis.call('ZREMRANGEBYSCORE', KEYS[1], 0, now - window)
local count = redis.call('ZCARD', KEYS[1])
if count < limit then
  redis.call('ZADD', KEYS[1], now, now .. '-' .. math.random(1000000))
  redis.call('PEXPIRE', KEYS[1], window)
  return 1
end
return 0
成员要带随机后缀去重:同一毫秒内多个请求的时间戳相同会被 ZSet 覆盖成一条。

易错点

  • 每个请求留一条记录,高频限流时内存与 ZSet 开销明显,固定窗口计数更省
  • 窗口与限值要与业务匹配,过严会误伤正常流量

数据来源与参考

  • Redis 官方文档:EVAL 与 ZSet 组合的限流模式说明
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌