跳转到内容

消费模式与再均衡

用途:解释“消费突然变慢/重复消费/某实例负载畸高”

方式 说明 适用
Push(推) 客户端长轮询模拟推送,SDK 管理线程与批量 绝大多数在线场景
Pull(拉) 应用自己控制拉取节奏与位点 批处理、需要精细流控(如按 DB 能力消费)

长轮询:无新消息时 Broker 挂起请求一段时间,兼顾实时性与空轮询开销。

  • 集群模式下,组内实例分摊 Topic 的队列;实例数 > 队列数时,多出的实例空闲(这是“加了机器不涨吞吐”的常见原因)。
  • 分配策略:平均分配、一致性哈希、环形分配等;策略不同,再均衡时的抖动不同。
  • 广播模式:每个实例消费全量,位点本地保存,重启会重放或漏消费。

触发:实例上下线、订阅关系变化、队列数变化。风险:

  1. 订阅关系不一致:同一消费者组内不同实例订阅的 Topic/Tag 不同,会导致消息“看起来丢了”(被别的实例按不同过滤条件消费掉)。这是生产环境最高频的疑难问题之一——同组订阅必须完全一致。
  2. 重复消费:再均衡瞬间位点提交与实际处理不一致,靠幂等兜底。
  3. 消费暂停:再均衡期间有短暂停顿,实例数频繁变化(弹性伸缩、健康检查抖动)会持续制造停顿。
方式 行为 风险
自动提交 SDK 周期性提交 崩溃时“已提交但未处理完” → 丢;或“处理完未提交” → 重复
手动提交 处理完再提交 更可靠,代码需保证每条/每批完成后提交

从哪个位点开始:CONSUME_FROM_LAST_OFFSET(新组默认,只消费新消息)/ CONSUME_FROM_FIRST_OFFSET(回溯全部,慎用,可能瞬间打爆下游)/ 按时间戳回溯。

  1. 队列数 ≥ 目标并发度(实例数 × 每实例线程数会受队列数上限约束)。
  2. 批量消费(一次拉多条,一次提交位点)提升吞吐,但增大“部分失败”的处理复杂度。
  3. 消费线程数与下游能力匹配:下游是 DB 时,消费并发过高只会造成锁等待。
  4. 单条耗时是根本:优化外部调用、加缓存、改异步,比调线程更有效。
  5. 监控:消费 TPS、堆积量(broker offset − consumer offset)、消费耗时 P99、重试次数。
误区 修正
同组不同实例订阅不同 Tag 拆成不同消费者组
实例数无限加 超过队列数无效
新组从最早位点开始消费 历史消息瞬间灌入,下游被打挂
只监控 TPS 不监控堆积 堆积是延迟事故的先行指标
手动提交放在处理前 失败时消息被确认,等于丢消息
  • Apache RocketMQ 官方文档:Consumer 最佳实践、订阅关系一致性
  • Martin Kleppmann《数据密集型应用系统设计》第 11 章(消费与再均衡)