Appearance
如何限制重复和过载:Dedup、Rate Limit 与 Concurrency Limit
前置:重试怎样避免放大故障:Backoff、Retry Budget 与 Idempotency
核心问题:同样是“限制请求”,Dedup、Rate Limit 与 Concurrency Limit 各自阻止哪一种系统失控,为什么不能互相替代?
Queue at-least-once 投递同一 job 两次,worker 先查 dedup record,第二次直接标记已处理。API 允许 60 req/min,即使 semaphore=20,也需 token bucket 控制一分钟总请求。
Mental Model
Reliability 不是“多 retry 几次”,而是 deadline、attempt、budget、idempotency、degradation、approval 与 cancellation 共同决定一个 logical operation 如何收敛。
Deduplication
Deduplication 识别重复消息/调用并复用或拒绝已处理结果。它与幂等互补:去重尽量不再执行,幂等保证即使执行也不产生额外效果。
Rate Limiting
Rate limit 控制时间窗口吞吐,concurrency limit 控制同时在途请求。两者常同时需要。Rate Limit 约束单位时间内请求量,保护 provider quota 或业务公平性;常见 token bucket/leaky bucket。
Concurrency Limiting
两者常同时需要。Concurrency Limit 约束 in-flight 工作数量,保护连接池、CPU、内存和下游并发容量。即使 QPS 很低,一个慢请求堆积也可能需要 semaphore/worker limit。
最佳值要用容量测试,不是越高越好。
三种限制解决的是三个不同问题
这三个机制经常一起出现,但限制对象不同:
text
Dedup → 同一个 logical work 不要重复提交/执行
Rate Limit → 一段时间内最多允许多少请求
Concurrency → 同一时刻最多允许多少 in-flight work例如 Provider 允许每分钟 600 次请求,但连接池只能稳定承载 20 个并发:Rate Limit 可能完全没超,Concurrency Limit 仍然必须阻止第 21 个请求立即进入。
Dedup 又是另一回事:即使系统还有容量,一个已经用相同 operation_id 成功提交过的支付也不应该再次执行。
Failure Modes
把 Concurrency Limit 当成 Rate Limit
症状: 只用 Semaphore 限制 in-flight,就认为满足每秒请求上限。
为什么危险: 快速请求仍可超过 QPS,慢请求又可能占满并发。
处理: 分别实现 in-flight concurrency 与 time-window/token-bucket rate limit。
如何验证
| Case | 断言 |
|---|---|
| 把 Concurrency Limit 当成 Rate Limit | 高频快速 Fake Tool 下 QPS 与 max in-flight 都不越界。 |
自测
- 同一请求重复三次、每秒请求太多、同时在飞请求太多,分别该由 dedup、rate limit、concurrency limit 哪个机制处理?
- 只做 rate limit 为什么仍可能把一个慢 Provider 的并发连接撑爆?