第 11 章 · 限流第 9 页,共 9 页
好几台服务器一起把关,怎样共用一个计数?
每台服务器各数各的,会放行几倍于上限的请求;把计数放进共用的计数缓存,又会多出等待、少算和故障的问题。
为什么需要
百家菜早已不只一台服务器。(站在一组服务器前面、把请求分给它们的组件)把请求轮流交给几台服务器,每台上都装着限流器。如果每台各自计数,一个请求者的请求分到 3 台,每台只看到三分之一,都以为它没有超,3 台加起来就放行了 3 倍的上限。
怎样做
办法是把计数放到每台服务器都查得到的地方,通常是一个,例如 Redis,它把数据放在里,读写极快。你平时说的「手机内存 256G」其实是长期保存照片和 App 的存储空间;这里的内存是电脑干活时临时放东西的地方,很快,一断电就清空,正适合存不停更新、丢了也无大碍的计数。它在图上起的作用,我们叫它「计数缓存」。你在手机里清理的「缓存」是 App 存下的临时文件;这里的缓存是另一台电脑,暂存要很快取到的数据。每台服务器都去那里读出、判断、写回,大家数的就是同一个数。
共用一个数又带来新问题。两台服务器几乎同时收到同一个请求者的请求:服务器 1 读出 6,服务器 2 也读出 6;两台都判断没超,各自放行,各自写回 7。放行了 2 个,计数只加了 1,后面就会多放进请求。结果取决于谁先谁后,这叫(race condition)。它并不罕见:同时到来的请求越多,也就是越需要限流时,越容易少算(Redis 的限流教程,2026);安全研究者还演示过,让 20 到 30 个请求同一刻到达,就能绕过防止反复猜密码的限流(网络安全公司 PortSwigger,2023)。解决办法是让计数缓存一步完成「读出、判断、写回」,中间不让别人插进来,这叫(atomic operation);「原子」指不可分割,与快慢无关。
在下图里调节服务器的台数,在「各数各的」和「共用一个计数」之间切换;再选「慢动作:两台同时数」,看计数怎样少算、多放进了几个,换成一步完成以后又怎样。
各数各的,还是共用一个数
先看这里先看读数「12 秒里一共放行」:3 台服务器各数各的,智能厨具程序 12 秒里发出的 24 个请求全部放行,是上限的 3 倍;改成「共用一个计数」,只放行 8 个,但每个请求的路多了两跳,见图下的两条路程。
- 送达
- 被拒绝,退回时带着 429:服务器答复「请求过多」
- 一个点代表一批请求,N 是这一批的个数
一个请求要走的路
多出来的两跳:每个请求都要等它们走完
每一格是一跳:数据从一台机器传到下一台。格子只表示先后和多少,不是实测的时间。
各数各的:每台服务器都只看到一部分请求,3 台加起来放行了 24 个,是上限 8 个的 3 倍。
代价是什么
共用计数的代价首先是等待:每个请求都要多走一趟,到计数缓存读出、判断、写回。也有的服务不追求一个精确的共用计数:Cloudflare 在每个数据中心(集中摆放大量服务器的机房)各自计数,计数的更新可能滞后几秒,限流生效之前,会有少量超出上限的请求先到达网站自己的服务器(2026)。
计数缓存也可能出故障。限流器查不到计数时只能二选一:(fail open),暂时放行所有请求,网站照常能用,但失去了保护,有程序在刷请求时,服务器可能被压垮;或者(fail closed),暂时拒绝所有请求,保护还在,可正常用户也被挡在门外,计数缓存成了(它一坏,整个网站就跟着停下)。在第二张图里比较这两种选择。
计数缓存坏了:全部放行,还是全部拒绝
先看这里把计数缓存切到「故障」,再切换两种选择,看读数和服务器框底部的负载条(送来的工作占服务器能力的几成,满了就是过载):「全部放行」时服务器被压垮,读者的请求一大半失败;「全部拒绝」时服务器很空闲,读者却全被挡在门外。
- 送达
- 被拒绝,退回时带着 429:服务器答复「请求过多」
- 排队等太久,失败了
- 一个点代表一批请求,N 是这一批的个数
计数缓存正常:限流器拒绝了出错程序的 4,473 个请求,读者照常访问。这时「查不到计数时」这项选择不起作用。
在线支付公司 Stripe、打车平台 Uber 等选择失败放行:Stripe 在限流代码出错或计数服务停止工作时一律放行(2017)。检查的组件一出错就拒绝,后果可能很大:2025 年 6 月 12 日,谷歌云负责检查配额和权限的组件反复崩溃,全球大量请求失败;多数区域在一小时内开始恢复,整个事件约 7.5 小时后结束,改进措施之一就是让这些检查在出错时放行(2025)。登录、发验证码这类一旦失守代价很高的操作,可以选择失败拒绝;同一个网站,可以对不同的操作做不同的选择。
资料来源
以下资料均于 2026-10-19 访问。
- Build 5 Rate Limiters with Redis: Fixed Window, Sliding Window, Token Bucket, and Leaky Bucket
- Smashing the state machine: the true potential of web race conditions
- Request rate calculation
- Rate limiting rules
- Scaling your API with rate limiters
- Uber's Rate Limiting System
- Multiple GCP products are experiencing Service issues.