
211工程院校贵州大学管理学院硕士研究生、全国百强城商行资讯科技部五级专技工程师、互联网金融行业资深DevOps研发工程师、金融科技运维自动化平台研发项目经理。曾在国内多家知名互联网公司 平安科技、微众银行、顺丰科技、魅族任职. 具有多年国内一线互联网公司自动化运维平台设计与开发经验。
1
前言
2
假设主题T1有四个分区,当前只有一个消费者C1,隶属于消费者组G1;消费者订阅主题T1,此时消费者C1将收到主题T1全部四个分区的消息,如下图所示:


倘若群组G1中有4个消费者,那么每个消费者都可以分配到一个分区,如下图所示:

继续向群组中添加更多的消费者,若消费者的数量超过了分区的数量时,那么就会有一部分的消费者会闲置,如下图所示:

向消费者群组中增加消费者,每个消费者只处理Topic中的一部分分区内的消息,是实现横向伸缩消费能力的主要方式。通常情况下Kafka的消费者会做一些较高延迟的操作,比如将数据处理后写入HDFS或者是对数据进行耗时的运算。在这种情况下,消费者对于数据的消费与处理速度是跟不上数据的生成速度的,此时可以通过增加更多消费者的方式分担负载,通常为主题创建多个分区是十分必要的,这样就可以在负载增长的时候加入更多的消费者。
3
横向扩展消费者组
在Kafka的实际应用过程中,也会存在多个应用服务从同一个主题中读取数据的情况,那么就应该通过扩展消费者组的方式来实现,这样属于不同群组的消费者就都可以获取到同一个Topic中的全部消息了,如下图所示:

4
分区再均衡


5
分区分配策略
5.1
RoundRobinAssignor分配策略


下面再看隶属于同一群组中的消费者订阅的主题不同的情况,若群组中内消费者订阅的主题是不同的,那么在执行分区分配的时候就不是完全的轮询分配了,会出现分区分配不均匀的情况。此处需要注意的是,如果某个消费者没有订阅某个Topic,那么在分区分配时,此消费者是分配不到这个Topic中的任何分区的。假设有如下场景,消费者组内有3个消费者C1、C2、C3,共同订阅了三个主题T0、T1、T2,若每个主题中分别有1、2、3个分区,其中消费者C1订阅了主题T0,消费者C2订阅了主题T0、T1,消费者C3订阅了主题T0、T1、T2,那么订阅的所有分区可以标识为:

最终分配的结果为:

5.2
RangeAssignor分配策略
本策略是以主题为基础的,在主题中根据数字编号对可用的分区排序,在消费者组中将消费者根据字典顺序排列。分区分配的依据是采用Topic中的分区总数除以消费者总数,来确定分配给每个消费者的分区个数,需要注意的是若不能平均分配的话,额外的分区将会分配给前几个消费者。假设有如下场景,消费者C1、C2都订阅了主题T0和T1且每个主题都有四个分区,那么要订阅的所有分区的标识为:




综上可见这样的分配其实是不均匀的,如果类似的情况不断扩大则会出现部分消费者过载的情况。
5.3
StickyAssignor分区分配策略
本策略有两个目标, 首先是要实现分区分配要尽可能地均匀,其次当发生分区再平衡发生时,分区的分配会尽可能的与上次的分配结果保持一致,目的是为了防止分区的消费者发生变化,这有助于节约开销,也有助于避免消息重复消费的问题发生。需要注意的是,当以上两点发生冲突的时候,第一个目标是优先于第二个目标的。假设有如下场景,有三个消费者C1、C2、C3,它们都订阅了4个主题T0、T1、T2、T3且每个主题有2个分区,那么要订阅的所有分区的标识为:


上述的分配结果中保留了上一次分配中对于消费者C1和C3的所有分配结果,并将原来消费者C2中分配的分区转移到了C1和C3中,最终消费者C1和C3的分区分配保持了均衡。若发生了分区再平衡,对于同一个分区而言,可能会出现之前的消费者和新指派的消费者不是同一个的情况,这就会导致消息的重复消费和浪费系统资源的情况。StickyAssignor策略如同其名字中的单词"sticky"一样,让分配的策略具备一定"粘性",以实现尽可能的让两次分配的结果是相同的,进而减少系统资源的损耗和其他异常情况的发生。下面看一下隶属于同一群组中的消费者订阅的主题不相同时分区分配策略结果是怎样的。假设有如下场景,群组内有3个消费者C1、C2、C3同时有三个主题T0、T1、T2,这三个主题分别有1、2、3个分区,消费者C1订阅了主题T0,消费者C2订阅了主题T0、T1,消费者C3订阅了主题T0、T1、T2,那么所要订阅的所有分区标识为:




若此时消费者C1离开了群组,那么StickyAssignor策略分配的结果是:
以上的分区分配结果较为理想,体现出了StickyAssignor策略所具有的两大特点,一是分区要尽可能的均衡,二是在发生分区再平衡时,分区的分配会尽可能的与上次的分配结果保持相同。
6
结束语






