四种主流限流算法详解:固定窗口、滑动窗口、漏桶与令牌桶
在高并发系统中,限流(Rate Limiting) 是保障服务稳定性的重要防线。面对突发流量,合理的限流策略能有效防止系统雪崩。目前主流的限流算法主要有四种:固定窗口、滑动窗口、漏桶(Leaky Bucket)和令牌桶(Token Bucket)。它们各有优劣,适用于不同场景。
本文将深入对比这四种算法的原理、优缺点及适用场景,助你做出更合理的技术选型。
固定窗口限流(Fixed Window)
✅ 原理
将时间划分为固定的窗口(如 1 小时),每个窗口内只允许一定数量的操作(如 10 次)。计数器在窗口开始时重置。
示例:1 小时内最多允许 10 个用户操作
✅ 优点
实现最简单:只需一个计数器 + 时间戳
资源开销极低
❌ 缺点
存在“边界突刺”问题
比如:
第 59 分钟:10 个请求集中到达
第 61 分钟(新窗口):又来 10 个请求
2 分钟内处理了 20 个请求,远超预期负载,可能压垮服务器
📌 适用场景
对精度要求不高、流量平稳的内部接口
快速原型验证
滑动窗口限流(Sliding Window)
✅ 原理
时间窗口是“滑动”的,以更小的时间单元(如 1 分钟)为步长向前推进。每次请求都会检查过去 N 个单元内的总请求数是否超限。
示例:
总窗口:1 小时
滑动单位:1 分钟
在第 59 分钟时,实际检查的是 [59min, 1h59min) 这个区间(逻辑上)
✅ 优点
有效缓解边界突刺问题,即使请求集中在窗口末尾,也会被后续窗口“拉平”
比固定窗口更平滑、更贴近真实流量控制
❌ 缺点
实现较复杂:需维护多个时间片的计数(可用 Redis ZSet 实现)
滑动单位的选择影响效果
单位越小 → 精度越高,但存储和计算开销越大
单位越大 → 效果趋近于固定窗口
📌 适用场景
需要较高精度的 API 网关限流
用户行为分析类限流(如“1 小时最多发 5 条消息”)
漏桶限流(Leaky Bucket)✅ 推荐用于输出限流
✅ 原理
请求进入一个“桶”,桶以固定速率向外“漏水”(处理请求)
桶有容量上限,若桶满,则新请求被拒绝
示例:
桶容量:10
处理速率:每秒 10 个请求(即每 0.1 秒处理 1 个)
若 1 秒内来了 11 个请求 → 第 11 个被丢弃
✅ 优点
输出速率恒定,保护下游服务不被突发流量冲击
能有效平滑突发流量
❌ 缺点
无法应对短时突发合法请求
即使系统有能力处理一批请求,也必须排队逐个处理,响应延迟高
不适合需要“瞬时高并发”的场景(如秒杀)
📌 适用场景
控制向第三方 API 的调用频率
日志上报、消息推送等后台任务限流
令牌桶限流(Token Bucket)✅ 推荐用于输入限流
✅ 原理
系统以固定速率生成令牌(如每秒 10 个),存入桶中
桶有最大容量(如 10)
每次请求需先获取一个令牌,有令牌才能执行;否则拒绝或等待
示例:
令牌生成速率:10 个/秒
桶容量:10
若空闲一段时间,桶满(10 个令牌)
此时可瞬间处理 10 个并发请求
✅ 优点
支持突发流量:只要桶中有令牌,就能立即处理
高并发友好:多个请求可同时获取令牌并执行
更符合“用户期望”——短时间内的合法突发应被允许
❌ 缺点
需要合理设置令牌生成速率和桶容量
若桶容量过大,可能失去限流意义
📌 适用场景
Web API 接口限流(如登录、下单)
区分用户等级的差异化限流(VIP 用户消耗更少令牌)
需要兼顾平滑性与突发处理能力的场景
🔍 四种算法对比总结
💡 推荐组合:
对外提供 API → 令牌桶(支持突发,用户体验好)
调用第三方服务 → 漏桶(防止自己打爆对方)
✅ 结语
没有“最好”的限流算法,只有“最合适”的。
如果你追求简单快速,用固定窗口;
如果你需要精确控制时间窗,用滑动窗口;
如果你要保护下游服务,用漏桶;
如果你要兼顾突发与稳定性,令牌桶是首选。
在实际项目中,结合 Redisson、Sentinel 或自研组件,你可以轻松实现上述任一策略。合理限流,既是技术,也是艺术。
📌 延伸阅读:
阿里 Sentinel 的滑动窗口 + 令牌桶混合模型
Guava RateLimiter 的令牌桶实现原理