限流的四种姿势,以及我们最终选的那个
做开放接口时被问"限流用什么算法"。这个问题没法直接回答,因为四种常见算法保护的对象不一样。
固定窗口计数器最简单:一分钟内最多 N 次。但它有边界突刺——第 59 秒和下一分钟第 1 秒之间可以瞬间挤进 2N 个请求。滑动窗口把窗口切成小格统计,抹掉了突刺,实现也不复杂,是大多数场景的起步选择。
漏桶和令牌桶的差别更微妙:漏桶把请求排队,以恒定速率放行,约束的是出口的平滑,适合保护脆弱的下游;令牌桶按固定速率生成令牌,桶里有存货就允许突发,约束的是总量,适合保护自己(比如登录尝试、搜索次数)。

| 算法 | 突发流量 | 典型场景 |
|---|---|---|
| 固定窗口 | 边界突刺 | 粗粒度统计、内部工具 |
| 滑动窗口 | 平滑 | API 通用限流 |
| 漏桶 | 不允许,恒速流出 | 保护下游/调用第三方 |
| 令牌桶 | 允许桶内突发 | 保护自身核心接口 |
我们最终落地的是"两级":网关层滑动窗口挡明显异常,业务层令牌桶保护核心接口,超限返回 429 并带 Retry-After。另外一条经验值得记:限流参数不在代码里,在配置里——线上调阈值是常态,每次都发版太蠢了。
至于分布式限流,把计数器挪到 Redis 就行,注意用 Lua 保证"读-判-写"原子。别一开始就上复杂架构,单机的滑动窗口够用很久。