目标
当真实瓶颈是每条消息一次数据库往返时,加消费者数量只会改账单不会改吞吐。先量每个阶段的速率、调当前绑定的阶段、改完再量——约束会迁移,表格要跟着走。批量摊销往返成本几乎总是第一且最大的杠杆。
步骤要点
- 度量端到端管线:绘制各阶段吞吐与处理耗时,系统容量等于最慢阶段的速率而非各阶段希望的加总。
- 诊断绑定阶段:定位它慢的原因——可并行却串行、逐条往返可批量、或下游限速。
- 拉对应的杠杆:CPU 可并行就加消费者并发,往返主导就批量,下游受限就协商或缓冲。
- 重新找绑定阶段:每次改动后重测,瓶颈会移动,下一轮瞄准新的约束。
- 峰值下验证排空:重放峰值流量,确认积压有界或在恢复窗口内排空且下游健康。
排错提示
加了很多消费者吞吐纹丝不动,说明瓶颈不在消费并发而在下游或往返数,先画阶段表;修了第一阶段吞吐没动是约束迁移了,每轮之后重新测量;峰值回放时下游 CPU 打满说明转移了瓶颈而非解决,容量要一起规划。
适用边界
吞吐上限最终受下游存储写入能力约束,队列侧优化不能替代数据库扩容;批量提高单条消息的失败影响面,需配幂等重试与死信设计。
代码示例
stage table (initial):
consume->parse 8,000 msg/s
validate 8,000 msg/s
db upsert 640 msg/s <- BINDING
cause: 1 round-trip per message (2.1ms x N)
round 1: batch upserts (200/batch)
db upsert 640 -> 14,800 msg/s
new binding: validate 8,000 (regex per msg)
round 2: precompiled validators, 2 workers
validate 8,000 -> 22,000 msg/s
new binding: consume parse (8k, io-bound)
round 3: 3 partitions, 3 consumers
parse 8,000 -> 23,400 msg/s
peak replay (12,000 msg/s): lag peaks 4.2s,
drains in 11 min, db CPU 61% (headroom ok)