| 结构 | 字段 tokens 与 ts,速率 rate、桶容量 burst |
|---|---|
| 补充 | tokens 取 burst 与 tokens 加 elapsed*rate 的较小值 |
| 判定 | 令牌不少于 1 时放行并减 1 |
Lua 脚本示意
Lua 脚本示意
local rate = tonumber(ARGV[1])
local burst = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
local t = redis.call('HMGET', KEYS[1], 'tokens', 'ts')
local tokens = tonumber(t[1]) or burst
local ts = tonumber(t[2]) or now
local delta = math.max(0, now - ts) / 1000
local filled = math.min(burst, tokens + delta * rate)
local allowed = 0
if filled >= 1 then
filled = filled - 1
allowed = 1
end
redis.call('HSET', KEYS[1], 'tokens', filled, 'ts', now)
redis.call('PEXPIRE', KEYS[1], math.ceil(burst / rate * 2000))
return allowed与滑动窗口相比,令牌桶允许桶内突发(不超过 burst),长窗口平滑性略弱;两种都可用 Lua 在单次往返内完成。