漏桶算法(Leaky Bucket)与 令牌桶算法(Token Bucket)
特性 | 解释 |
---|---|
出水速率恒定 | 不管入水多快,出水速率固定,比如1秒100次 |
拒绝突发流量 | 桶满了就直接拒绝,不等待排队 |
整形输出 | 平滑请求流量,防止抖动、突刺 |
比如:
特性 | 解释 |
---|---|
允许突发请求 | 桶里积累的令牌允许短时暴增请求 |
均匀填充令牌 | 按固定速率添加令牌,比如1秒100个 |
灵活速率 | 正常小流量可以慢慢用令牌,大流量爆发时快速消耗令牌 |
比如:
比较维度 | 漏桶算法 | 令牌桶算法 |
---|---|---|
出口流量 | 恒定速率,超限丢弃 | 灵活突发,令牌够可以爆发 |
突发流量处理能力 | ❌ 不允许 | ✅ 允许短时突发 |
实现复杂度 | 简单 | 稍复杂 |
应用场景 | 带宽整形、严格限速 | 秒杀、抢购、高并发接口 |
✅ 在秒杀、抢购、接口突发流量场景,
✅ 应该用令牌桶算法(Token Bucket)。
因为:
-- KEYS[1]: 令牌桶的Key
-- ARGV[1]: 最大容量
-- ARGV[2]: 每秒放入多少令牌
-- ARGV[3]: 当前时间戳(秒)
local capacity = tonumber(ARGV[1])
local rate = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
local lastTokens = tonumber(redis.call('hget', KEYS[1], 'tokens') or capacity)
local lastTimestamp = tonumber(redis.call('hget', KEYS[1], 'timestamp') or now)
local delta = math.max(0, now - lastTimestamp)
local newTokens = math.min(capacity, lastTokens + (delta * rate))
if newTokens < 1 then
return 0
else
redis.call('hset', KEYS[1], 'tokens', newTokens - 1)
redis.call('hset', KEYS[1], 'timestamp', now)
return 1
end
✅ 逻辑:
rate
个令牌流量模式 | 推荐算法 |
---|---|
秒杀抢购、允许短时冲击 | ✅ 令牌桶(Token Bucket) |
带宽控制、强制匀速 | ✅ 漏桶(Leaky Bucket) |