在高并发系统中,限流(Rate Limiting) 是保障服务稳定性的重要防线。面对突发流量,合理的限流策略能有效防止系统雪崩。目前主流的限流算法主要有四种:固定窗口、滑动窗口、漏桶(Leaky Bucket)和令牌桶(Token Bucket)。它们各有优劣,适用于不同场景。

本文将深入对比这四种算法的原理、优缺点及适用场景,助你做出更合理的技术选型。

固定窗口限流(Fixed Window)

✅ 原理

将时间划分为固定的窗口(如 1 小时),每个窗口内只允许一定数量的操作(如 10 次)。计数器在窗口开始时重置。

示例:1 小时内最多允许 10 个用户操作

✅ 优点

  • 实现最简单:只需一个计数器 + 时间戳

  • 资源开销极低

❌ 缺点

  • 存在“边界突刺”问题

比如:

  1. 第 59 分钟:10 个请求集中到达

  2. 第 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 用户消耗更少令牌)

  • 需要兼顾平滑性与突发处理能力的场景

🔍 四种算法对比总结

算法

是否允许突发

实现难度

适用方向

典型工具

固定窗口

❌ 否

简单计数

自研计数器

滑动窗口

⚠️ 有限

⭐⭐⭐

精确时间窗

Redis ZSet

漏桶

❌ 否

⭐⭐

输出限流(保护下游)

Guava RateLimiter(部分实现)

令牌桶

✅ 是

⭐⭐

输入限流(保护自身)

Redisson RRateLimiter、Sentinel

💡 推荐组合:

对外提供 API → 令牌桶(支持突发,用户体验好)

调用第三方服务 → 漏桶(防止自己打爆对方)

✅ 结语

  • 没有“最好”的限流算法,只有“最合适”的。

  • 如果你追求简单快速,用固定窗口;

  • 如果你需要精确控制时间窗,用滑动窗口;

  • 如果你要保护下游服务,用漏桶;

  • 如果你要兼顾突发与稳定性,令牌桶是首选。

在实际项目中,结合 Redisson、Sentinel 或自研组件,你可以轻松实现上述任一策略。合理限流,既是技术,也是艺术。

📌 延伸阅读: