Kafka 消费者组与 Rebalance¶
1. Rebalance 触发条件¶
flowchart TD
R["触发 Rebalance(分区重新分配)"]
R --> A["消费者加入组\n(新实例启动)"]
R --> B["消费者离开组\n(实例下线/崩溃)"]
R --> C["消费者心跳超时\n(session.timeout.ms 内未发心跳)"]
R --> D["Topic 分区数变化\n(增加分区)"]
Rebalance 的代价:Rebalance 期间,整个消费者组停止消费,直到重新分配完成。频繁 Rebalance 会导致消费停顿,是 Kafka 性能问题的常见原因。
2. 三种分区分配策略¶
| 策略 | 分配方式 | 优点 | 缺点 | 为什么选它 |
|---|---|---|---|---|
| Range | 按分区范围分配给消费者 | 简单 | 分配不均匀(前几个消费者分到更多) | 简单场景 |
| RoundRobin | 轮询分配所有分区 | 均匀 | Rebalance 后变动大 | 需要均匀分配时 |
| Sticky | 尽量保持上次的分配结果 | 减少迁移,Rebalance 影响小 | 实现复杂 | 生产环境推荐 |
3. 避免频繁 Rebalance 的配置¶
# 消费者心跳间隔(建议为 session.timeout.ms 的 1/3)
# 为什么是 1/3:保证在超时前至少发送 3 次心跳,容忍 2 次失败
heartbeat.interval.ms=3000
# 会话超时时间(消费者超过此时间未发心跳则被踢出)
session.timeout.ms=10000
# 消费者两次 poll 的最大间隔(处理时间过长会触发 Rebalance)
# 如果业务处理时间可能超过 5 分钟,需要调大此值
max.poll.interval.ms=300000
# 每次 poll 的最大消息数(减少单次处理时间,避免超过 max.poll.interval.ms)
max.poll.records=500
4. Rebalance 流程¶
sequenceDiagram
participant C1 as Consumer 1
participant C2 as Consumer 2
participant GC as Group Coordinator
C1->>GC: 发送 JoinGroup 请求
C2->>GC: 发送 JoinGroup 请求
GC-->>C1: 选为 Group Leader,返回成员列表
GC-->>C2: 返回 JoinGroup 响应
C1->>GC: 发送 SyncGroup(携带分配方案)
C2->>GC: 发送 SyncGroup
GC-->>C1: 返回分配结果(消费 P0、P1)
GC-->>C2: 返回分配结果(消费 P2)
注意:Rebalance 期间所有消费者停止消费,等待分配完成后才继续。
5. 最佳实践¶
| 场景 | 建议 |
|---|---|
| 消费者处理时间长 | 调大 max.poll.interval.ms,减小 max.poll.records |
| 消费者频繁重启 | 检查应用稳定性,避免频繁触发 Rebalance |
| 需要减少 Rebalance 影响 | 使用 Sticky 分配策略 |
| 分区数规划 | 分区数 ≥ 消费者数,避免消费者空闲 |