🔄 Kafka Consumer Rebalance 流程详解

从触发条件到分区分配,完整梳理 Rebalance 的全生命周期、分配策略与最佳实践

⚡ 一、Rebalance 触发条件

👤

Consumer 加入 / 离开

新的 Consumer 加入 Group,或已有的 Consumer 异常退出(心跳超时、主动关闭)

📋

Consumer 订阅变更

Consumer 使用 subscribe() 动态改变订阅的 Topic 列表

📦

Topic 分区数变更

Topic 的 Partition 数量增加或减少(如管理员执行了扩分区操作)

💔

Consumer 心跳超时

Consumer 在 session.timeout.ms 内未发送心跳,Coordinator 将其踢出 Group

🐌

处理时间过长

单次 poll() 超过 max.poll.interval.ms,被认为"不活跃"

☠️

Coordinator 故障转移

Group Coordinator 所在 Broker 宕机,新 Coordinator 接管后触发 Rebalance

📌 关键点:Rebalance 是 Group 级别 的——一旦某个 Consumer 变动,整个 Consumer Group 内所有 Consumer 都会暂停消费参与 Rebalance!这就是为什么频繁 Rebalance 会严重影响吞吐。

🗺️ 二、Rebalance 完整流程(Step by Step)

Phase 1:寻找 Coordinator

准备阶段
1

确定 GroupCoordinator

Consumer 根据 __consumer_offsets Topic 的 Partition 分布算法:

hash(group_id) % num_partitions

2

连接 Coordinator

找到负责该 Consumer Group 的 GroupCoordinator 节点(某台 Broker),建立 TCP 连接

// 消费者端配置
group.id = "my-order-group"
// __consumer_offsets 默认 50 个分区
// hash("my-order-group") % 50 → 决定哪个 Broker 是 Coordinator

Phase 2:加入 Group(JoinGroup)

核心协议 · 同步阻塞
3

STOP — 停止消费 ⚠️

Group 内所有 Consumer 暂停 poll()!
正在处理的消息可能被中断,这是 Rebalance 对业务最大的影响

4

发送 JoinGroup 请求

每个 Consumer 向 Coordinator 发送 JoinGroup 请求,携带:
• group_id
• member_id
• 协议类型 & 协议列表
• 订阅的 Topic 列表

5

选举 Leader Consumer

Coordinator 从所有成员中选举一个 Leader(通常是第一个发送 JoinGroup 的成员),其余为 Follower

Phase 3:同步分组状态(SyncGroup)

Leader 分配 · 全局同步
6

Leader 执行分区分配 🎯

Coordinator 向 Leader 发送完整的成员列表 + 可用 Topic/Partition 信息。

Leader 根据分配策略计算分配方案,生成 assignment map

7

发送 SyncGroup

所有 Consumer 发送 SyncGroup 请求。
Leader:携带完整的分配方案
Follower:assignment 为空

8

Coordinator 下发方案

Coordinator 收集到 Leader 的分配方案后,将各自的 assignment 返回给每个 Consumer

Phase 4:恢复消费

结束
9

接收 Assignment

各 Consumer 收到自己被分配到的 Partition 列表,更新本地状态

10

RESET Offset(按需)

根据分配结果重置 Offset:
• 新分配的 Partition → 按 auto.offset.reset 策略
• 已有历史的 Partition → 从上次提交位置继续

11

RESUME — 恢复消费 ✅

Consumer 恢复 poll() 循环,开始从新分配的 Partition 拉取消息并处理

🎨 三、Rebalance 交互架构图

Kafka Cluster (Broker) 🎯 GroupCoordinator 管理 Consumer Group 元数据 触发 & 协调 Rebalance Topic Partitions P0 C0 P1 C1 P2 C0 P3 C1 P4 C2 P5 C2 👑 Consumer-C0 (Leader) Assigned: [P0, P2] state: STABLE → JOINING action: 执行分配策略 ✓ 接收全部成员信息 ✓ 计算 assignment map Consumer-C1 (Follower) Assigned: [P1, P3] state: STABLE → JOINING action: 等待分配结果 ⏳ 空 assignment 上报 Consumer-C2 (Follower) Assigned: [P4, P5] state: STABLE → JOINING action: 等待分配结果 ⏳ 空 assignment 上报 🆕 New Consumer-C3 ← 触发 Rebalance! 加入 Group → 重新分配分区 ⚠️ 所有 Consumer 暂停 ① FindCoordinator ② JoinGroup (All) ③ 你是 Leader! 成员列表 ↓ Leader 计算分配方案... ④ SyncGroup (含分配方案) ⑤ Assignment [P0,P2] [P1,P3] → C1 [P4,P5] → C2 JoinGroupRequest FindCoordinator JoinGroup Elect Leader SyncGroup 下发 Assignment ↑ Rebalance 全过程(通常持续数秒 ~ 数十秒,期间 Group 所有消费者停止工作)↑

⚖️ 四、Partition 分配策略

Kafka 支持多种分区分配策略,通过 partition.assignment.strategy 配置:

Range(默认)
  • 按 Topic 逐个分配
  • P0-P3 分 2 个 Consumer → C0:[P0,P1], C2:[P2,P3]
  • ⚠️ 可能导致不均匀:多 Topic 时某些 Consumer 分到更多分区
  • 公式:N = ⌊partitions/consumers⌋
RoundRobin(轮询)
  • 跨 Topic 所有分区轮询分配
  • P0→C0, P1→C1, P2→C0, P3→C1... 交替分配
  • ✅ 分配更均匀(多 Topic 场景下优势明显)
  • 要求所有 Consumer 订阅相同的 Topic 列表
Sticky(粘性)
  • 尽量保留上次的分配关系
  • Rebalance 时只移动必要的分区
  • ✅ 减少不必要的分区迁移
  • 两轮分配:先 Sticky(保序),再均匀化
Cooperative(协作式)
  • Kafka 2.4+ 新增,渐进式 Rebalance
  • 不需要 STOP THE WORLD
  • ✅ 逐步迁移分区,不影响其他 Consumer
  • 配合 StickyAssignor 使用效果最好
策略均匀性Rebalance 影响适用场景Kafka 版本
Range⭐⭐⭐ 单 Topic OK大(全局暂停)单 Topic、简单场景全版本
RoundRobin⭐⭐⭐⭐ 更均匀大(全局暂停)多 Topic、需均衡负载全版本
Sticky⭐⭐⭐⭐中(减少迁移)高可用、减少抖动0.11+
Cooperative⭐⭐⭐⭐⭐小(渐进式!)生产环境推荐2.4+

⚙️ 五、防 Rebalance 关键参数调优

参数默认值作用调优建议
session.timeout.ms 45s Consumer 心跳超时阈值 适当增大(如 20-30s),避免网络波动误判
heartbeat.interval.ms 3s 心跳发送间隔 设为 session.timeout 的 1/3,即 6-10s
max.poll.interval.ms 5min 两次 poll() 最大间隔 如果业务处理慢,必须调大!否则会被踢出
max.poll.records 500 每次 poll 最大消息数 处理慢时减小此值(如 100-300),缩短单次处理时间
partition.assignment.strategy Range 分区分配策略 多 Topic 推荐 RoundRobinCooperativeStickyAssignor

⚠️ 经典坑:你的 Consumer 处理一条消息要 10 秒,max.poll.interval.ms 还是默认 5 分钟。看起来没问题?但如果一次拉了 500 条,500 × 10s = 5000s ≫ 300s,直接超时被踢出!
解决方案:max.poll.records=50max.poll.interval.ms=600000

💡 减少 Rebalance 的黄金法则:
1. 避免在高峰期重启 Consumer / 滚动发布
2. 合理设置超时参数(session.timeout ≥ 3 × heartbeat.interval)
3. 保证 Consumer 心跳线程和处理线程隔离
4. 升级 Kafka ≥ 2.4,使用 CooperativeStickyAssignor 实现渐进式 Rebalance
5. 监控 consumer-lag 和 rebalance 频率,设置告警

📌 Rebalance 一句话记忆

找 Coordinator全员 JoinGroup选 Leader 分配SyncGroup 同步恢复消费
核心痛点:STW(Stop-The-World)—— Rebalance 期间整个 Group 停止工作。解决方案:CooperativeSticky + 参数调优