一、固定窗口算法(Fixed Window)
原理:
将时间划分为固定长度的窗口(如1秒、1分钟),每个窗口内统计请求次数,超过阈值则拒绝后续请求。例如:每秒限流100次,窗口结束后计数器清零。
优缺点:
- 优点:实现简单(如使用Redis的计数器),适合快速部署。
- 缺点:存在窗口切换时的边界突刺问题(如第1秒最后10秒和第2秒前10秒可能通过双倍请求)。
适用场景:
对限流精度要求不高、突发流量容忍度较高的场景。
二、滑动窗口算法(Sliding Window)
原理:
将固定窗口细分为多个时间片(如1秒分为5个200ms的片),统计最近N个时间片内的总请求量,窗口随时间推移“滑动”更新。
优缺点:
- 优点:平滑限流效果,减少边界突刺问题。
适用场景:
需要精确控制瞬时流量的高并发系统(如电商秒杀)。
三、令牌桶算法(Token Bucket)
原理:
系统以固定速率向桶中添加令牌,请求需获取令牌才能通过。桶满时丢弃多余令牌,无令牌则拒绝请求。
例如:桶容量100,每秒添加10个令牌,允许突发100次请求。
优缺点:
- 优点:支持突发流量,灵活性高(通过调整桶容量和生成速率)。
- 缺点:需定时生成令牌(如Redis的Lua脚本维护令牌状态)。
适用场景:
需要应对短期流量高峰的API服务(如社交媒体接口)。
四、漏桶算法(Leaky Bucket)
原理:
请求像水流一样进入漏桶,系统以固定速率处理请求(桶底“漏水”)。桶满时溢出请求被拒绝。
优缺点:
- 优点:严格平滑流量,避免突发压力(如Nginx限流模块的核心算法)。
- 缺点:无法应对突发流量,可能造成请求延迟。
适用场景:
需要严格控制处理速率的场景(如支付系统)。
五、算法对比与选型建议
算法 | 突发流量支持 | 流量平滑性 | 实现复杂度 | 典型工具 |
---|---|---|---|---|
固定窗口 | ❌ | ❌ | 低 | Redis计数器 3 |
滑动窗口 | ❌ | ✔️ | 中 | Redis Sorted Set 3 |
令牌桶 | ✔️ | ❌ | 高 | Guava RateLimiter 5 |
漏桶 | ❌ | ✔️ | 高 | Nginx限流模块 5 |
选型建议:
- 需允许突发流量(如秒杀)→ 令牌桶
- 需严格平滑流量(如数据库保护)→ 漏桶
- 分布式场景→ 滑动窗口+Redis
- 快速实现→ 固定窗口(配合短时间窗口减少误差)
总结
限流算法的核心目标是在系统过载前保护服务可用性。固定窗口和滑动窗口基于时间窗口统计,令牌桶和漏桶则通过速率控制实现限流。实际应用中常结合Redis实现分布式限流,并根据业务场景选择算法。例如,API网关可混合使用滑动窗口(精准控制)和令牌桶(应对突发),达到平衡稳定性和灵活性的效果。