Kafka学习笔记(十四) --- 消费者组重平衡的全流程解析

之前说过,消费者组的重平衡需要借助Kafka Broker端的Coordinator组件,在Coordinator的帮助下完成消费者组的分区重分配。下面详细说一说这个流程。

  • 触发和通知

触发条件:组成员数量变化;订阅主题数量变化;订阅主题的分区数变化。

在实际生产环境中,因命中第一个条件而引发的重平衡最常见。另外,消费者组中的消费者实例依次启动也属于第一种情况,也就是每次启动消费者组时,必然会触发重平衡。

重平衡是如何通知其他消费者实例的?答案是心跳线程。

自0.10.1.0版本开始,社区引入一个单独线程专门执行心跳请求发送。Kafka JAVA消费者需要定期地发送心跳请求到Broker端的协调者,以表明它还活着。当Coordinator决定开启新一轮重平衡后,会将 "REBALANCE_IN_PROGRESS" 封装进心跳请求的响应中,通知消费者实例。另外,consumer端参数heart.interval.ms,就是设置心跳间隔,其实真正作用是控制重平衡通知的频率,如果设置成很小的一个值,消费者就能很快感知重平衡的开启。

  • 消费者组状态机

重平衡一旦开启,Broker端Coordinator组件就要开始忙了,主要涉及控制消费者组的状态流转。当前,Kafka设计了一套消费者组状态机来帮助Coordinator完成整个重平衡流程。严格来说,它属于非常底层设计,Kafka官网压根没提,但是还是了解一下好,可以帮助我们搞懂消费者组的设计原理,比如消费者组的过期位移 (Expired Offsets) 删除 等。

Kafka为消费者组定义了5种状态,它们分别是:Empty、Dead、PreparingRebalance、CompletingRebalance和Stable。

                                                      

各个状态的流转:

                            

解释:一个消费者组最开始是Empty状态,当重平衡开启后,会被置于PreparingRebalance状态等待成员加入,之后变更到CompletingRebalance状态等待分配方案,最后流转到Stable状态完成重平衡。当有新成员加入或已有成员退出时,消费者组的状态从Stable直接跳到PreparingRebalance状态,此时,所有现成成员就必须重新申请加入组。当所有成员退出组后,消费者组的状态变更为Empty。Kafka定期自动删除过期位移的条件是,组要处于Empty状态。

  • 重平衡流程

重平衡的完整流程需要消费者端和协调者组件共同参与才能完成。消费者端重平衡分为两步:分别是加入组和等待领导者消费者分配方案。这两步分别对应两种请求:JoinGroup请求和SyncGroup请求。当组成员加入组时,会向协调者发送JoinGroup请求。在该请求中,每个成员都要将自己订阅的主题上报,这样协调者就能收集所有成员订阅信息。一旦收集全部成员的JoinGroup请求后,协调者会从这些成员中选择一个担任消费者组的领导者。通常情况下,第一个发送JoinGroup请求的成员会自动成为领导者。这里的领导者不同于前面的领导者副本,这里的领导者是具体的消费者实例,既不是副本,也不是协调者。领导者消费者的任务是收集所有成员的订阅信息,然后根据这些信息,制定具体的分区的消费分配方案。

选出领导者之后,协调者会把消费者组订阅信息封装进JoinGroup请求的响应体中,然后发给领导者,由领导者统一做出分配方案,进入到下一步:发送SyncGroup请求,将刚刚做出的分配方案发给协调者。值得注意的是,其他成员也会向协调者发送SyncGroup请求,只不过请求体中并没用实际内容。这一步主要目的是让协调者接收分配方案,然后统一以SyncGroup响应方式分发给所有成员,这样内部所有成员都知道自己该消费哪些分区,消费者组进入Stable状态,即开始正常的消费工作。下面展示JoinGroup请求和SyncGroup请求的处理过程:

   

  • Broker端重平衡场景剖析

场景一:新成员入组。

是指组处于Stable状态,有新成员加入,这里并不是说的组刚启动时的场景。当协调者收到新的JoinGroup请求后,它会通过心跳请求响应的方式通知组内现有的所有成员,强制它们开启新一轮的重平衡。下面用一张时序图来说明协调者一端是如何处理新成员入组的。

                              

场景二:组成员主动离组。

何为主动离组?就是指消费者实例所在线程或进程调用close()方法主动通知协调者要退出。这个场景涉及第三类请求:LeaveGroup请求。协调者受到该请求后,依然会以心跳响应方式通知其他成员,看下图:

                               

场景三:组成员崩溃离组。

崩溃离组是指消费者实例出现严重故障,突然宕机导致的离组,并且协调者通常要过一段时间才能感知到,有消费者端参数session.timeout.ms控制。看下图:

                             

场景四:重平衡协调者对组内成员提交位移的处理。

正常情况下,每个组内成员都会定期汇报位移给协调者。当重平衡开启时,协调者给与成员一段缓冲时间,要求每个成员必须在这段时间内快速上报自己位移信息,然后再开启正常的JoinGroup/SyncGroup请求发送。看下图:

                         

目前社区正在对目前的重平衡流程做较大程度改动,如果你不了解这些基础设计原理,后面想深入学习这部分内容很十分困难。

标注:这个系列文章是本人在极客时间专栏---kafka核心技术与实战中的学习笔记

    https://time.geekbang.org/column/article/101171

发布了37 篇原创文章 · 获赞 20 · 访问量 4951

猜你喜欢

转载自blog.csdn.net/qq_24436765/article/details/102661367