消费者组的重平衡流程 : 让组内所有的消费者消费哪些主题分区达成一致
- 重平衡要在 Coordinator 协助下完成整个消费者组的分区重分配
触发与通知
重平衡的 3 个触发条件:
- 组成员数量发生变化
- 订阅主题数量发生变化
- 订阅主题的分区数发生变化
重平衡过程通知其他消费者 : 靠消费者端的心跳线程 (Heartbeat Thread)
消费者会定期发送心跳请求 (Heartbeat Request) 到 Broker 的协调者,来表明存活
- Kafka 0.10.1.0 前,发送心跳请求是在消费者主线程完成的,用
KafkaConsumer.poll
的那个线程 - Kafka 0.10.1.0 后,用单独的心跳线程来专门执行心跳请求发送
重平衡的通知机制 : 通过心跳线程来完成
- 当协调者要开启重平衡,会将
REBALANCE_IN_PROGRESS
封装进心跳请求的响应中,发给消费者 - 当消费者实例发现心跳响应中包含
REBALANCE_IN_PROGRESS
,就得知开始重平衡
heartbeat.interval.ms
: 控制重平衡通知的频率
- 要消费者更快通知,就调小点,让消费者更快感知到重平衡开启
消费者组状态机
Kafka 有一套消费者组状态机 (State Machine),来帮助协调者完成重平衡
消费者组的 5 种状态 :
状态 | 含义 |
Empty | 组内没有成员,但消费者组还存在已提交的位移数据,且这些位移尚未过期 |
Dead | 组内没有成员,但组的元数据信息已经在协调者被移除。协调者组件保存着当前向它注册过的所有组信息 |
PreparingRebalance | 消费者组准备重平衡,所有成员要重新请求加入消费者组 |
CompletingRebalance | 消费者组下所有成员已经加入,各个成员等待分配方案(老版本 : AwaitingSync) |
Stable | 消费者组的稳定状态 : 重平衡已经完成,组内各成员能正常消费数据 |
状态机的各状态流转 :
- 消费者组最开始是 Empty 状态
- 当重平衡开始,以 PreparingRebalance 状态等待成员加入
- 变成 CompletingRebalance 状态等待分配方案
- 再转成 Stable 状态完成重平衡
- 当新成员加入或已有成员退出时,消费者组的状态从 Stable 直接跳到 PreparingRebalance 状态:所有现存成员要重新申请加入组
- 当所有成员都退出组后,消费者组会变为 Empty
- Kafka 定期自动删除过期位移的条件:组要在 Empty 状态 (当消费者组停了 (超过 7 天) : Kafka 可能把该组的位移数据删除)
日志的输出:尝试定期删除过期位移
- 只有 Empty 状态的组,才能执行过期位移删除
Removed ✘✘✘ expired offsets in ✘✘✘ milliseconds.
消费者重平衡流程
消费者的重平衡两个步骤:
- 加入组 , 等待领导者消费者 (Leader Consumer) 分配方案
- 两个步骤分别对应请求:JoinGroup 请求 , SyncGroup 请求
JoinGroup 请求的处理过程 :
- JoinGroup 作用 : 将组成员订阅信息发送给领导者消费者 (通常 : 第一个发送 JoinGroup 的成员是领导者),等领导者分配好方案后,重平衡进入到 SyncGroup 阶段
SyncGroup 请求的处理流程 :
- SyncGroup 目的 : 让协调者把领导者的分配方案发给各个组内成员
- 当所有成员都成功接收到分配方案后,消费者组进入到 Stable 状态 (正常消费)
Broker 重平衡场景
新成员入组
新成员入组 : 组处于 Stable 状态后,有新成员加入
- 当协调者收到新 JoinGroup 后,会通过心跳请求通知组内所有成员,强制开启重平衡
组成员主动离组
主动离组 : 消费者调用 close()
主动通知协调者要退出
- 协调者收到 LeaveGroup 后,以心跳响应通知其他成员
组成员崩溃离组
崩溃离组 : 消费者挂了,而导致离组
- 崩溃离组是被动,协调者要等待时间 (
session.timeout.ms
) 才能感知
重平衡提交位移
- 当重平衡开启时,要求每个成员要时间内快速上报各自位移信息
- 再开始 JoinGroup/SyncGroup 请求发送