暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

必知必会!Kafka分区分配策略

稻壳编程 2021-06-20
325

211工程院校贵州大学管理学院硕士研究生、全国百强城商行资讯科技部五级专技工程师、互联网金融行业资深DevOps研发工程师、金融科技运维自动化平台研发项目经理。曾在国内多家知名互联网公司 平安科技、微众银行、顺丰科技、魅族任职. 具有多年国内一线互联网公司自动化运维平台设计与开发经验。



 1 

 前言

应用程序通过KafkaConsumer实例化出消费者对象并订阅Topic,并在这个Topic之上消费与处理数据。若想要知道队列中的数据是如何消费的,首先需了解消费者和消费者组的概念。消费者是从属于消费者群组的,若一个消费者群组中的所有消费者订阅的都是相同的主题,那么群组中的每个消费者都只是接收主题中的一部分分区内的数据。Kafka默认的消费逻辑是,位于某个主题中的一个分区只能被同一个消费者组中的一个消费者消费。

 2 

消费者的横向扩展

假设主题T1有四个分区,当前只有一个消费者C1,隶属于消费者组G1;消费者订阅主题T1,此时消费者C1将收到主题T1全部四个分区的消息,如下图所示:

若在群组G1中增加一个消费者C2,那么每个消费者将分别从两个分区接收消息,假设消费者C1接收分区0和分区2, 消费者C2接收分区1和分区3的消息,如下图所示:

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

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

向消费者群组中增加消费者,每个消费者只处理Topic中的一部分分区内的消息,是实现横向伸缩消费能力的主要方式。通常情况下Kafka的消费者会做一些较高延迟的操作,比如将数据处理后写入HDFS或者是对数据进行耗时的运算。在这种情况下,消费者对于数据的消费与处理速度是跟不上数据的生成速度的,此时可以通过增加更多消费者的方式分担负载,通常为主题创建多个分区是十分必要的,这样就可以在负载增长的时候加入更多的消费者。


 3 

  横向扩展消费者组

在Kafka的实际应用过程中,也会存在多个应用服务从同一个主题中读取数据的情况,那么就应该通过扩展消费者组的方式来实现,这样属于不同群组的消费者就都可以获取到同一个Topic中的全部消息了,如下图所示:

在Kafka中,横向伸缩消费者与消费者组是不会对性能造成影响的。


 4 

分区再均衡

在Kafka的Topic中,通常都会有多个分区,每个分区会按照一定规则分配给对应的消费者,当某个消费者出现故障无法接收并处理消息时,那就必须对分区进行重新分配,以保证消息能够正常的被消费和处理。如下图所示,原主题中存在两个分区,分别对应一个消费者组中的两个消费者,若消费者Consumer2出现故障,那么就必须通过分区再平衡的方式,让Consumer3来消费Partition2中的数据,如下图所示:

简言之,分区的所有权从一个消费者转移到另一个消费者,我们把这种现象称之为分区再均衡。那么什么情况下会发生分区再平衡呢?隶属于相同消费者组中的所有消费者共同读取某个主题中的所有分区,当一个新的消费者加入群组时,它将会读取原本是由其他消费者读取的消息;当一个消费者关闭或发生崩溃时,该消费者会离开群组,那么原本由它读取的分区将由群组中的其他消费者读取;在主题发生变化,比如管理员变更了主题中分区的数量时,也会触发分区在均衡。所以导致发生分区再平衡的原因可以总结为—当主题分区发生变化时、或有新消费者加入群组时、或群组中有消费者挂掉时,Kafka会触发分区再均衡操作。 那分区再均衡有哪些优缺点呢?分区再平衡的优势在于能为消费者群组带来高可用性与伸缩性;但其缺点在于在发生再均衡这一期间内,消费者是无法读取信息的,所以这将会造成消费者群组会出现一小段时间不可用的情形。所以在应用Kafka的过程中,需要避免无用的分区再均衡发生。当发生分区再均衡时,Kafka守护进程中会有如下输出:


 5 

分区分配策略

在实例化Kafka消费者对象时,消费者对象参数partition.assignment.strategy用来设置消费者与订阅主题之间的分区分配策略。默认情况下此参数的值为RangeAssignor,即采用RangeAssignor分区分配策略。Kafka支持的分区分配策略包括三种,分别是RangeAssignor、RoundRobinAssignor和StickyAssignor。那么这三种分区分配策略有什么区别呢?

 5.1 



RoundRobinAssignor分配策略


本策略的原理是,如果同一个消费者组内所有消费者订阅的主题都是相同的,那么策略的分区分配也是均匀的。假设在如下场景中,群组中的消费者订阅的主题都是相同的,消费者组中存在两个消费者C1、C2都订阅了主题T0、T1,若每个主题中都有3个分区,那么所订阅的所有分区可以标识为:

最终分配的结果为:

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

最终分配的结果为:

之所以会产生这样的分配结果,是因为由于消费者C1只订阅了T0主题,那么分区T0P0会被分配给C1;消费者C2订阅了主题T0、T1,但由于T0中的分区已经被C1消费了,那么分区T1P0会被分配给消费者C2;已知T1分区同时被消费者C2、C3订阅,那么分区T1P1会分配给消费者C3;T2主题仅被消费者C3订阅了,所以T2主题中的所有分区都只能交给消费者C3消费。


 5.2 

  RangeAssignor分配策略

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

最终分配的结果为:

之所以产生这样的分配结果,是因为群组中存在消费者C1、C2,已知T0、T1主题中都存在四个分区,在这两个主题内部分别用分区数除以消费者数,最终每个消费者都将从主题中取出两个分区订阅。这样的分配是很均匀的,那么此分配策略是否能一直保持如此均匀的分配呢,我们再看另外一种情况,也就是分区数和消费者数不能整除的情况。假设有如下场景,群组中存在消费者C1、C2,有两个主题T0、T1其中都有3个分区,那么要订阅的所有分区标识为:

当不能整除时,前面的消费者会分配到额外的分区,那么此时的分配结果为:

综上可见这样的分配其实是不均匀的,如果类似的情况不断扩大则会出现部分消费者过载的情况。


 5.3 


StickyAssignor分区分配策略


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

最终的分配结果如下:

这样的分配结果似乎看上去与RoundRobinAssignor策略分配的结果相同,现假设此时消费者C2脱离了群组,那么群组将会执行分区再平衡操作,若采用的是RoundRobinAssignor策略,那么分配结果将是:上述的分配结果中保留了上一次分配中对于消费者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,那么所要订阅的所有分区标识为:

如果此时采用RoundRobinAssignor策略,那么最终的分配结果如下:

若此时消费者C1脱离了群组,那么RoundRobinAssignor策略的分配结果为:

若采用的是StickyAssignor策略,那么最终的分配结果为:

若此时消费者C1离开了群组,那么StickyAssignor策略分配的结果是:

以上的分区分配结果较为理想,体现出了StickyAssignor策略所具有的两大特点,一是分区要尽可能的均衡,二是在发生分区再平衡时,分区的分配会尽可能的与上次的分配结果保持相同。


 6 

结束语

如果本文可以对您的工作学习带来帮助,请扫描左侧赞赏码以资鼓励作者;文章勘误请扫描右侧二维码联系作者。


文章转载自稻壳编程,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论