【背景】 做了 15 年中间件,带过三个团队做高并发服务。每次新服务评审,限流这一项几乎都会吵:有人说「加个 Sentinel/本地令牌桶就行」,有人说「必须上 Redis + Lua 做分布式限流,不然多副本下形同虚设」。我见过两种极端事故:
- 本地限流:单副本 QPS 上限 1000,4 副本实际打出去 4000,下游 MySQL 直接被打崩——「限流」形同虚设;
- 分布式限流:Redis 集群一次主从切换,限流判断全部超时,兜底策略配的是「放行」,下游被一波流量冲垮——「保护手段」本身成了放大器。
【常见分歧 / 几种做法】
- 默认本地限流(Sentinel / Guava RateLimiter),只在「明确要全局配额」的入口(API 网关、对外接口)才上 Redis + Lua;
- 默认分布式限流,理由是「多副本下本地限流不严谨」,Redis 挂了走本地兜底;
- 两级:本地做第一道(快、零依赖),分布式做第二道(准、全局),代价是每次请求多一次 RTT;
- 干脆不默认做,等业务真被打挂了再补(我见过太多这种)。
【我的倾向与理由】 我倾向做法 1:本地默认、分布式按需,理由有三:
- 依赖面:把 Redis 加进「每个请求的关键路径」,等于把限流的可用性绑定到 Redis 的可用性上,这本身就违背「保护下游」的初衷;
- 多数场景其实不需要全局精确:保护的是「单副本能承受的下游能力」,本地限流对单副本的保护语义是对的;
- 全局配额是少数场景(对外 API、付费接口、第三方配额),为少数场景把多数场景的复杂度抬上去,不划算。
但有个前提容易被忽略:本地限流要生效,副本数必须可控、且单副本容量稳定(HPA 频繁扩缩、单机性能受邻居影响时,「每副本 1000」的语义就漂了)。
【想听大家】
- 你们线上限流的默认姿势是哪种?触发上分布式限流的具体条件是什么(全局配额?副本数 > N?下游是共享资源?)?
- Redis 挂了,你们的兜底策略是「放行」还是「拒绝」?为什么?
- HPA 频繁扩缩的场景下,本地限流的「每副本上限」怎么和副本数联动,有没有踩过坑?
- 两级限流(本地 + 分布式)多出的 RTT,在 P99 敏感的链路上你们怎么权衡?
欢迎带具体场景和数字来聊,空谈「看情况」的我们就当没看见 :)
0赞
0收藏
0楼层