什么是 Kafka 的重平衡机制?

#中间件#面试八股

什么是 Kafka 的重平衡机制?

结论:重平衡(Rebalance)是消费组内"分区所有权"的重新分配过程:组协调器(GroupCoordinator)收集成员、选出组 Leader、由组 Leader 计算分配方案,再同步给所有成员。它保证"一个分区只被一个消费者消费",代价是分配期间消费暂停、位点提交可能混乱、消息可能重复。

一、两种协议的执行差异

Eager(旧协议,Range/RoundRobin/Sticky)
  Trigger ──> 所有成员 revoke 全部分区 ──> JoinGroup ──> SyncGroup ──> 恢复消费
              ▲ 全组停摆,分区越多停得越久

Cooperative(增量协作,CooperativeSticky)
  Trigger ──> JoinGroup ──> SyncGroup(只下发新增分区)
           ──> 成员仅撤销"不再属于自己"的分区 ──> 再一轮 SyncGroup 完成迁移
              ▲ 未受影响的分区持续消费,停摆范围小
对比项EagerCooperative
停摆范围全组仅迁移中的分区
轮次1 轮通常 2 轮
重复消费多少
配置RangeAssignor 等CooperativeStickyAssignor

二、触发条件

触发源具体场景是否可避免
成员加入扩容消费者、发布重启用静态成员可避免重启触发
成员离开缩容、进程正常退出计划内操作可控
心跳超时GC 停顿、网络抖动、线程卡死调大 session.timeout.ms、排查 GC
处理超时单次 poll 间隔超过 max.poll.interval.ms减小 max.poll.records、异步化处理
订阅变化正则订阅匹配到新 Topic避免用正则订阅核心业务
分区数变化Topic 扩容分区规划阶段预留分区

三、重平衡对业务的影响

  • 消费暂停:Eager 协议下全组停止拉取,分区多、成员多时可能持续数秒到数十秒;
  • 重复消费:已处理但未提交位点的消息会被新 owner 重新拉取;
  • 位点回退风险:撤销分区时若提交了旧位点,可能覆盖新进度(旧协议常见坑);
  • 延迟抖动:重平衡常与发布、扩容同时发生,容易被误判为"消息延迟"。

四、减少重平衡的配置

# 消费者端
session.timeout.ms=45000                  # 心跳超时,需大于 3 倍 heartbeat
heartbeat.interval.ms=3000                # 心跳间隔
max.poll.interval.ms=300000               # 两次 poll 的最大间隔
max.poll.records=200                      # 单批条数,控制处理时长
partition.assignment.strategy=org.apache.kafka.clients.consumer.CooperativeStickyAssignor
group.instance.id=order-consumer-1        # 静态成员:重启不触发重平衡
enable.auto.commit=false

group.instance.id 是关键:配置静态成员后,实例重启在 session.timeout.ms 内重新加入,协调器认为还是同一个成员,不会触发全组重平衡。滚动发布场景收益非常明显。

五、监控与排查

# 观察组成员、分配、LAG
kafka-consumer-groups.sh --bootstrap-server 10.0.0.31:9092 \
  --describe --group order-group

# 组状态:Stable / PreparingRebalance / CompletingRebalance / Dead
kafka-consumer-groups.sh --bootstrap-server 10.0.0.31:9092 \
  --describe --group order-group --state

日志里出现 (Re)join group、Preparing to rebalance group、Revoking previously assigned partitions 就说明正在重平衡。频繁出现通常意味着成员不稳定:GC 停顿、poll 处理过慢、或者实例在反复重启。

六、常见追问

  • 重平衡会丢消息吗? 不会因为重平衡本身丢,但"处理未完成就提交位点"会丢;"处理完成未提交"会重复。本质仍是提交时机。
  • 消费者比分区多会怎样? 多出的消费者分不到分区,空转但仍是组成员,一旦有成员退出就会接手,属于热备。
  • 重平衡期间生产会受影响吗? 不会。生产端只与分区 Leader 交互,重平衡只发生在消费侧。
  • 怎么做到"发布不触发重平衡"? 静态成员 + CooperativeStickyAssignor + 合理的 session.timeout.ms,并保证单批处理时间远小于 max.poll.interval.ms。

小结

  • 重平衡是消费组分区所有权的再分配,由组协调器驱动、组 Leader 计算方案。
  • 触发源分三类:成员变化、心跳/处理超时、订阅或分区变化。
  • Eager 全组停摆,Cooperative 增量迁移,新项目应直接用 CooperativeStickyAssignor。
  • 静态成员 + 合理的超时参数是减少重平衡最有效的手段。
笔记加载中…