3. 常见限流算法详解(上):计数器算法、滑动窗口算法、漏桶算法
在金融低延迟场景中,限流算法的选择直接决定了系统的吞吐上限、响应抖动以及资源利用率。本章深入剖析三种经典限流算法的核心原理、数学特性、优劣势及适用边界,帮助架构师在低延迟与高精度之间做出合理权衡。
3.1 计数器算法(Counter Algorithm)
3.1.1 原理
计数器算法是最直观的限流实现。在固定时间窗口(如 1 秒)内维护一个计数器,每次请求到达时计数器加 1;当计数器达到预设阈值时,后续请求被拒绝;窗口结束后计数器重置为零。
核心逻辑伪代码:
// 固定窗口计数器限流
long currentTime = System.currentTimeMillis() / 1000; // 按秒分桶
if (currentTime != lastWindowStart) {
counter = 0;
lastWindowStart = currentTime;
}
if (counter < threshold) {
counter++;
return ALLOW;
} else {
return REJECT;
}
3.1.2 优缺点
| 维度 | 说明 |
|---|---|
| 优点 | 实现极简,仅需一个计数器和时间戳;内存占用 O(1);计算延迟为纳秒级,适合高频调用。 |
| 缺点 | 存在严重的窗口边界突刺问题:在窗口末尾和下一窗口开头,允许瞬间两倍阈值的流量通过,导致限流失效。 |
| 适用场景 | 对精度要求不高、允许短时毛刺的非核心业务;或作为前置快速过滤层。 |
金融避坑: 在交易峰值秒杀场景中,计数器算法的边界突刺可能让瞬时 QPS 翻倍,直接击穿下游数据库连接池。不建议用于核心交易链路。
3.1.3 适用场景
- 非关键路径的日志上报、监控指标采集。
- 客户端 SDK 侧的简易限流。
- 与其它算法组合使用,作为第一道粗粒度过滤。
3.2 滑动窗口算法(Sliding Window Algorithm)
3.2.1 原理
滑动窗口算法将固定窗口细分为多个小格(如 1 秒分为 10 个 100ms 的格子),每个格子独立计数。窗口随时间向前滑动,每次请求统计当前时间点所在窗口内所有格子的累计值。格子越细,精度越接近真正的匀速限流。
精度与性能的权衡: 格子数量越多,限流精度越高,但内存占用和计算开销也线性增长。金融低延迟场景通常选择 10~20 个格子,在精度与性能之间取得平衡。
3.2.2 优缺点
| 维度 | 说明 |
|---|---|
| 优点 | 消除了固定窗口的边界突刺问题;精度可通过调整格子数量灵活控制;实现相对简单。 |
| 缺点 | 内存占用 O(n),n 为格子数;每次请求需遍历窗口内所有格子求和,CPU 开销高于计数器算法;格子数过多时延迟增加。 |
| 适用场景 | 需要平滑限流、对边界突刺敏感的核心 API;如交易下单、风控校验。 |
3.2.3 适用场景
- 金融核心交易链路的限流保护。
- 对流量毛刺容忍度低的实时报价系统。
- 需要精确控制每秒请求数的网关层。
3.3 漏桶算法(Leaky Bucket Algorithm)
3.3.1 原理
漏桶算法将请求视为水滴,先注入一个固定容量的桶中,桶底部以恒定速率向外漏水(处理请求)。当桶满时,新请求被丢弃。漏桶强制输出速率恒定,无论输入流量如何波动。
关键参数:
- 桶容量(capacity): 最大允许的积压请求数,对应系统能容忍的最大突发。
- 漏水速率(leakRate): 每秒处理的请求数,即系统的恒定吞吐率。
- 当前水量(water): 桶中积压的请求数,随时间以漏水速率减少。
3.3.2 优缺点
| 维度 | 说明 |
|---|---|
| 优点 | 输出速率绝对平滑,无任何突刺;能有效吸收突发流量;实现简单,适合硬件和底层网络。 |
| 缺点 | 无法应对突发流量带来的低延迟要求——即使桶未满,请求也需排队等待;对短时爆发性业务不友好;参数调优困难。 |
| 适用场景 | 需要严格平滑输出的场景,如数据库写入限流、消息队列生产速率控制。 |
3.3.3 适用场景
- 数据库连接池的写入速率控制,防止打盘 I/O 打满。
- 日志采集与传输,避免后端存储被突发流量冲垮。
- 硬件设备(如网卡、FPGA)的流量整形。
3.4 三种算法对比总结
| 特性 | 计数器算法 | 滑动窗口算法 | 漏桶算法 |
|---|---|---|---|
| 输出平滑度 | 差(有边界突刺) | 较好(取决于格子数) | 极好(绝对恒定) |
| 内存开销 | O(1) | O(n) | O(1) |
| 计算延迟 | 极低(纳秒级) | 低(微秒级) | 极低(纳秒级) |
| 突发吸收能力 | 弱 | 中等 | 强(但增加排队延迟) |
| 低延迟友好度 | 高 | 高 | 低(排队引入等待) |
| 金融推荐度 | ⭐(非核心) | ⭐⭐⭐⭐(核心交易) | ⭐⭐⭐(后端保护) |