消费模式与再均衡
用途:解释“消费突然变慢/重复消费/某实例负载畸高”
两种消费方式
「两种消费方式」小节链接| 方式 | 说明 | 适用 |
|---|---|---|
| Push(推) | 客户端长轮询模拟推送,SDK 管理线程与批量 | 绝大多数在线场景 |
| Pull(拉) | 应用自己控制拉取节奏与位点 | 批处理、需要精细流控(如按 DB 能力消费) |
长轮询:无新消息时 Broker 挂起请求一段时间,兼顾实时性与空轮询开销。
消费者组与队列分配
「消费者组与队列分配」小节链接- 集群模式下,组内实例分摊 Topic 的队列;实例数 > 队列数时,多出的实例空闲(这是“加了机器不涨吞吐”的常见原因)。
- 分配策略:平均分配、一致性哈希、环形分配等;策略不同,再均衡时的抖动不同。
- 广播模式:每个实例消费全量,位点本地保存,重启会重放或漏消费。
再均衡(Rebalance)
「再均衡(Rebalance)」小节链接触发:实例上下线、订阅关系变化、队列数变化。风险:
- 订阅关系不一致:同一消费者组内不同实例订阅的 Topic/Tag 不同,会导致消息“看起来丢了”(被别的实例按不同过滤条件消费掉)。这是生产环境最高频的疑难问题之一——同组订阅必须完全一致。
- 重复消费:再均衡瞬间位点提交与实际处理不一致,靠幂等兜底。
- 消费暂停:再均衡期间有短暂停顿,实例数频繁变化(弹性伸缩、健康检查抖动)会持续制造停顿。
位点管理
「位点管理」小节链接| 方式 | 行为 | 风险 |
|---|---|---|
| 自动提交 | SDK 周期性提交 | 崩溃时“已提交但未处理完” → 丢;或“处理完未提交” → 重复 |
| 手动提交 | 处理完再提交 | 更可靠,代码需保证每条/每批完成后提交 |
从哪个位点开始:CONSUME_FROM_LAST_OFFSET(新组默认,只消费新消息)/ CONSUME_FROM_FIRST_OFFSET(回溯全部,慎用,可能瞬间打爆下游)/ 按时间戳回溯。
吞吐调优抓手
「吞吐调优抓手」小节链接- 队列数 ≥ 目标并发度(实例数 × 每实例线程数会受队列数上限约束)。
- 批量消费(一次拉多条,一次提交位点)提升吞吐,但增大“部分失败”的处理复杂度。
- 消费线程数与下游能力匹配:下游是 DB 时,消费并发过高只会造成锁等待。
- 单条耗时是根本:优化外部调用、加缓存、改异步,比调线程更有效。
- 监控:消费 TPS、堆积量(broker offset − consumer offset)、消费耗时 P99、重试次数。
常见误区
「常见误区」小节链接| 误区 | 修正 |
|---|---|
| 同组不同实例订阅不同 Tag | 拆成不同消费者组 |
| 实例数无限加 | 超过队列数无效 |
| 新组从最早位点开始消费 | 历史消息瞬间灌入,下游被打挂 |
| 只监控 TPS 不监控堆积 | 堆积是延迟事故的先行指标 |
| 手动提交放在处理前 | 失败时消息被确认,等于丢消息 |
延伸阅读
「延伸阅读」小节链接- Apache RocketMQ 官方文档:Consumer 最佳实践、订阅关系一致性
- Martin Kleppmann《数据密集型应用系统设计》第 11 章(消费与再均衡)