2. Rate Limiting 基础概念:限流算法概述与常见应用场景

限流(Rate Limiting)是分布式系统与 API 网关中控制流量进入速率的核心手段。其本质是在单位时间内限制请求数量,防止系统过载、资源耗尽或遭受恶意攻击。本节将系统梳理三种主流限流算法及其典型应用场景,为后续参数配置与缓存一致性测试奠定理论基础。

2.1 三大限流算法对比

算法 核心思想 流量特征 突发处理 适用场景
令牌桶 以固定速率向桶内投放令牌,请求需获取令牌才能通过 允许一定程度的突发流量 支持(桶内令牌积累) API 限流、微服务网关
漏桶 请求以固定速率从桶底漏出,超出桶容量的请求被丢弃 强制平滑,严格整形 不支持 流量整形、网络 QoS
滑动窗口 将时间划分为小窗口,统计窗口内请求数,窗口随时间滑动 接近实时,边界精度高 受窗口粒度限制 防刷、秒杀、计数器
选型提示: 令牌桶是业界最通用的限流算法,兼顾平均速率与突发能力;漏桶适合需要严格削峰填谷的场景;滑动窗口在分布式计数器与防刷场景中精度优于固定窗口。

2.2 令牌桶算法(Token Bucket)

令牌桶算法通过两个参数控制流量:桶容量(burst) 和 令牌生成速率(rate)。系统以恒定速率向桶中添加令牌,每个请求消耗一个令牌;若桶中令牌不足,请求被拒绝或等待。桶容量决定了允许的最大突发请求数。

令牌桶算法工作原理 令牌生成器 rate = 10 tokens/s 固定速率 令牌桶 容量 = 20 个令牌 请求进入 消耗 1 个令牌 有令牌? 请求通过 请求拒绝 关键参数: rate(令牌生成速率)→ 控制平均流量;burst(桶容量)→ 控制突发流量上限。 当桶满时,新生成的令牌被丢弃,防止无限积累。

2.3 漏桶算法(Leaky Bucket)

漏桶算法将请求视为水滴,以恒定速率从桶底漏出。桶容量固定,当桶满时新请求被丢弃。漏桶强制输出流量完全平滑,适合需要严格整形流量的场景,如网络 QoS 和数据库写入限流。

漏桶 vs 令牌桶核心区别: 漏桶的输出速率恒定,无法应对突发;令牌桶允许短时突发,但平均速率受控。漏桶更适用于下游处理能力固定的系统,令牌桶更适用于需要弹性响应的 API 网关。

2.4 滑动窗口算法(Sliding Window)

滑动窗口算法将时间轴划分为多个小窗口(如 1 秒),每个窗口维护一个计数器。窗口随时间向前滑动,过期窗口的计数被丢弃。当前总请求数为所有活跃窗口计数之和。相比固定窗口,滑动窗口避免了边界突刺问题。

滑动窗口算法示意图(窗口大小 = 5 秒) T₀ T₅ 窗口 1 计数: 15 窗口 2 计数: 22 窗口 3 计数: 18 窗口 4 计数: 25 窗口 5 计数: 12 时间滑动 已过期(丢弃) 当前总计数 = 92 滑动窗口通过细粒度分片消除固定窗口的边界突刺问题。窗口粒度越小,精度越高,但内存开销也越大。

2.5 常见应用场景

场景 推荐算法 典型配置 说明
API 限流 令牌桶 rate=100 req/s, burst=200 允许短时突发,保障 API 响应弹性
防刷(DDoS/爬虫) 滑动窗口 窗口=1s, 阈值=50 细粒度检测异常高频请求,快速阻断
流量整形 漏桶 漏出速率=50 req/s, 桶深=100 强制输出平滑,保护下游脆弱系统
秒杀/抢购 滑动窗口 + 令牌桶 窗口=100ms, 阈值=10 组合使用,兼顾精度与突发处理
数据库连接池限流 漏桶 漏出速率=10 conn/s 防止连接池被瞬时打满
常见误区: 固定窗口算法(如每分钟重置计数器)在窗口边界处容易出现流量突刺——请求在窗口末尾和下一窗口开头集中涌入,导致瞬时 QPS 翻倍。滑动窗口通过分片滑动有效缓解此问题,但会引入额外的内存与计算开销。

2.6 算法选型决策树

在实际项目中,算法选型需结合业务容忍度与系统资源。以下决策路径可供参考:

  1. 是否需要严格平滑输出? → 是 → 选择漏桶算法
  2. 是否需要应对突发流量? → 是 → 选择令牌桶算法
  3. 是否需要高精度边界控制? → 是 → 选择滑动窗口算法
  4. 场景复杂,需要组合策略? → 是 → 令牌桶 + 滑动窗口双层限流