限流算法与实现
四种经典的限流算法,每种都有适用的场景。从原理到代码实现,一文讲透。
一、为什么要限流
- 1.1 保护系统——防止流量超过处理能力
- 1.2 公平性——防止个别用户占用过多资源
- 1.3 成本控制——第三方 API 调用次数限制
二、固定窗口算法
- 2.1 原理——在一个固定时间窗口内计数,超过阈值则拒绝
- 2.2 代码实现——
AtomicLong+ 定时重置 - 2.3 临界问题——窗口切换时的”突刺”
- 2.4 优点——实现简单
- 2.5 缺点——不够平滑
三、滑动窗口算法
- 3.1 原理——将窗口细分为多个小窗口,随时间滑动
- 3.2 代码实现——环形数组 + 时间戳
- 3.3 Sentinel 的
LeapArray实现 - 3.4 优点——解决了临界问题
- 3.5 缺点——存储开销稍大
四、漏桶算法
- 4.1 原理——请求先进入”桶”,以固定速率流出
- 4.2 代码实现——
ScheduledThreadPoolExecutor - 4.3 优点——流量整形,平滑输出
- 4.4 缺点——无法处理突发流量
五、令牌桶算法
- 5.1 原理——以固定速率产生令牌,请求需要获取令牌
- 5.2 代码实现——Guava
RateLimiter - 5.3 预热模式——
RateLimiter.create(permitsPerSecond, warmupPeriod, unit) - 5.4 优点——允许一定的突发流量
六、四种算法对比
- 6.1 适用场景——突发 vs 平滑
- 6.2 分布式限流——Redis + Lua 实现
- 6.3 选择决策树
七、总结
- 固定窗口/滑动窗口——适合 QPS 限制
- 漏桶/令牌桶——适合流量整形
- Sentinel/Guava RateLimiter 已经实现了这些算法
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 谜思录!