文章目录
概述
我们知道kafka的topic可以被分成多个分区,消费者在集群模式下消费时一个消费组内的每个消费者实例只能消费到一个分区的消息,那么他们是怎么进行分区消费策略的设置的?默认是什么策略?能否存在不同消费者使用不同的分区分配策略?能否一个消费者设置两种分区分配策略?能否自己设置一个策略(自定义分区消费策略这部分会省略讲)?我们可以带着这些问题入手了解这部分的内容。
Kafka提供了消费者客户端参数partition.assignment.strategy来设置消费者与订阅主题之间的分区分配策略。默认情况下,此参数的值为org.apache.kafka.clients.consumer.RangeAssignor,即采用RangeAssignor分配策略。除此之外,Kafka还提供了另外两种分配策略:RoundRobinAssignor和StickyAssignor。消费者客户端参数partition.assignment·Strategy可以配置多个分配策略,彼此之间以逗号分隔。
分区分配策略
RangeAssignor分配策略
RangeAssignor分配策略的原理是按照消费者总数和分区总数进行整除运算来获得一个跨度,然后将分区按照跨度进行平均分配,以保证分区尽可能均匀地分配给所有的消费者。对于每一个主题,RangeAssignor策略会将消费组内所有订阅这个主题的消费者按照名称的字典序排序,然后为每个消费者划分固定的分区范围,如果不够平均分配,那么字典序靠前的消费者会被多分配一个分区。如:一个主题T,存在5个分区(p0,p1,p2,p3,p4),存在一个包含2个实例的消费组(n0,n1)。那么可能得消费是这样的,n0消费p0,p1,p2这3个分区,n2消费p3,p4这两个分区。
RoundRobinAssignor分配策略
RoundRobinAssignor 分配策略的原理是将消费组内所有消费者及消费者订阅的所有主题的分区按照字典序排序,然后通过轮询方式逐个将分区依次分配给每个消费者。RoundRobinAssignor分配策略对应的partition.assignment.strategy参数值为org.pache.kafka.clients.consumer.RoundRobinAssignor 。如:一个主题T,存在5个分区(p0,p1,p2,p3,p4),存在一个包含2个实例的消费组(n0,n1)。那么可能得消费是这样的,n0消费p0,p2,p4这3个分区,n1消费p1,p3这两个分区。
StickyAssignor
我们再来看一下StickyAssignor分配策略,"sticky"这个单词可以翻译为"黏性 的",Kafka从0.11.x版本开始引入这种分配策略,它主要有两个目的
(1)分区的分配要尽可能均匀。
(2)分区的分配尽可能与上次分配的保持相同。
当两者发生冲突时,第一个目标优先于第二个目标。鉴于这两个目标,StickyAssignor分配策略的具体实现要比RangeAssignor和RoundRobinAssignor这两种分配策略要复杂得多。如:消费组内有3个消费者(n0、n1和n2),它们都订阅了4个主题(t0、t1、t2、t3),
并且每个主题有2个分区。也就是说,整个消费组订阅了t0p0、t0p1、t1p0、t1p1、t2p0、t2p1、t3p0、t3pl这8个分区。最终的分配结果如下:
消货者n0:t0p0、t1p1、t3p0
消货者n1:t0p1、t2p0、t3p1
消货者n2:t1p0、t2p1
自定义分区分配策略
读者不仅可以任意选用Kafka提供的3种分配策略,还可以自定义分配策略来实现更多可选的功能。自定义的分配策略必须要实现org.apache.kafka.clients.consumer.intemnals.PartitionAssignor接口。
PartitionAssignor接口中定义了两个内部类:Subscription1和Assignmentc。
Subscription类用来表示消费者的订阅信息,类中有两个属性:topics和userDa ta分别表示消费者的订阅主题列表和用户自定义信息。PartitionAssignor接口通过subscription方来设置消费者自身相关的Subscription信息,注意到此方法中只有一个参数topics,与Subscription 类中的 topics的相呼应,但并没有体现有关userData的参数。为了增强用户对分配结果的控制,可以在subscriptionO方法内部添加一些影响分配的用户自定义信息赋子userData比如权重、IP地址、host或机架(rack)等。
总结
到这里能否存在不同消费者使用不同的分区分配策略?能否一个消费者设置两种分区分配策略?这两问题还没有结论,我们先直接给出答案------
这一切都是交由消费者协调器(ConsumerCoordinator)和组协调器
(GroupCoordinator)来完成的,它们之间使用一套组协调协议进行交互。在下一章节将继续讲解消费者协调器和组协调器,在这一章将详细说明kafka如何处理这两个问题。