local info = redis.call('HMGET', key, 'tokens', 'last_refill_time') local current_tokens = tonumber(info[1]) local last_refill_time = tonumber(info[2])
if now > last_refill_time then local delta = now - last_refill_time local filled = delta * rate current_tokens = math.min(capacity, current_tokens + filled) last_refill_time = now end
STEP5:扣减令牌与决策:判断令牌是否足够支持流量通过。
1 2 3 4 5
local allowed = false if current_tokens >= requested then current_tokens = current_tokens - requested allowed = true end
local key = KEYS[1] local capacity = tonumber(ARGV[1]) local rate = tonumber(ARGV[2]) local requested = tonumber(ARGV[3])
-- 获取 Redis 服务器当前时间(秒级和微秒级),保证分布式时钟一致性 -- 相比由客户端传入时间,使用 Redis 自身时间能避免服务器时钟不同步问题 local time_info = redis.call('TIME') local now = tonumber(time_info[1])
-- 获取当前桶的剩余令牌数和上次填充时间 local info = redis.call('HMGET', key, 'tokens', 'last_refill_time') local current_tokens = tonumber(info[1]) local last_refill_time = tonumber(info[2])
-- 初始化:如果 key 不存在,说明是第一次访问,默认桶是满的 if current_tokens == nilthen current_tokens = capacity last_refill_time = now end
-- 计算惰性填充 if now > last_refill_time then local delta = now - last_refill_time -- 计算这段时间生成的令牌:时间差 * 速率 local filled = delta * rate -- 令牌数不能超过桶容量 current_tokens = math.min(capacity, current_tokens + filled) -- 更新填充时间 last_refill_time = now end
-- 判断令牌是否足够 local allowed = false if current_tokens >= requested then current_tokens = current_tokens - requested allowed = true end