2. 限流算法基础(一):计数器与滑动窗口
在金融API网关中,限流是保障系统稳定性的第一道防线。本章深入剖析两种最基础的限流算法——计数器算法与滑动窗口算法,从原理、实现到金融场景的适用性,为你打下坚实的限流理论基础。
2.1 计数器算法(Fixed Window Counter)
2.1.1 原理与实现
计数器算法将时间划分为固定的窗口(如1秒、1分钟),每个窗口内维护一个计数器。请求到达时,若计数器未超过阈值则放行并计数+1;若超过阈值则拒绝。窗口结束时,计数器重置为0。
核心逻辑伪代码:
class FixedWindowCounter:
def __init__(self, limit, window_ms):
self.limit = limit # 窗口内最大请求数
self.window_ms = window_ms # 窗口大小(毫秒)
self.counter = 0
self.window_start = now()
def allow(self):
if now() - self.window_start > self.window_ms:
# 新窗口,重置
self.window_start = now()
self.counter = 0
if self.counter < self.limit:
self.counter += 1
return True
return False
2.1.2 优缺点分析
| 维度 | 说明 |
|---|---|
| 优点 | 实现简单,内存占用极低(仅需2个变量);时间复杂度O(1);适合对精度要求不高的场景 |
| 缺点 | 存在窗口边界突刺问题:在窗口末尾和下一个窗口开头,可能短时间内通过2倍阈值的请求量 |
| 适用场景 | 非关键路径的粗粒度限流、后台批处理任务、对突发容忍度较高的系统 |
金融场景避坑: 在支付、下单等核心链路中,计数器算法的边界突刺可能导致瞬间流量翻倍,引发数据库连接池打满或下游服务雪崩。务必谨慎使用。
2.1.3 边界突刺问题图解
下图展示了计数器算法在窗口切换时的典型突刺现象:
2.2 滑动窗口算法(Sliding Window)
2.2.1 原理与实现
滑动窗口算法将时间窗口细分为多个小格子(如1秒窗口分为10个100ms的格子),每个格子独立计数。窗口随着时间推移“滑动”,始终统计最近N个格子的总请求数。当总请求数超过阈值时拒绝新请求。
核心逻辑伪代码:
class SlidingWindowCounter:
def __init__(self, limit, window_ms, slot_ms):
self.limit = limit
self.slot_count = window_ms // slot_ms
self.slot_ms = slot_ms
self.slots = [0] * self.slot_count
self.current_index = 0
self.last_slot_time = now()
def allow(self):
self._advance_window()
total = sum(self.slots)
if total < self.limit:
self.slots[self.current_index] += 1
return True
return False
def _advance_window(self):
elapsed = now() - self.last_slot_time
slots_to_advance = elapsed // self.slot_ms
if slots_to_advance > 0:
# 滑动窗口,重置过期的格子
for i in range(min(slots_to_advance, self.slot_count)):
self.current_index = (self.current_index + 1) % self.slot_count
self.slots[self.current_index] = 0
self.last_slot_time += slots_to_advance * self.slot_ms
2.2.2 优缺点分析
| 维度 | 说明 |
|---|---|
| 优点 | 有效消除边界突刺,限流曲线平滑;精度可通过调整格子数量控制;适合对流量稳定性要求高的场景 |
| 缺点 | 内存占用随格子数线性增长(通常10~100个格子即可);实现复杂度略高于计数器;格子数过多时CPU开销增加 |
| 适用场景 | 金融核心交易链路、API网关、对突发流量敏感的实时系统 |
2.2.3 滑动窗口工作流程
下图展示了滑动窗口如何通过细粒度格子实现平滑限流:
2.3 两种算法对比总结
| 对比维度 | 计数器算法 | 滑动窗口算法 |
|---|---|---|
| 实现复杂度 | 极低(2个变量) | 中等(数组+指针维护) |
| 内存占用 | O(1) | O(N),N为格子数(通常10~100) |
| 边界突刺 | 严重(可达2倍阈值) | 无(平滑过渡) |
| 限流精度 | 粗粒度(窗口级别) | 细粒度(格子级别) |
| 金融场景推荐 | ❌ 不推荐核心链路 | ✅ 推荐用于交易、支付等 |