从客户端的角度入手,同时涉及客户端和服务端的内容,以便深入地挖掘Kafka的实现原理,从底层的概念去构建Kafka的知识体系。
分区分配策略
Kafka提供了消费者客户端参数partition.assignment.strategy来设置消费者与订阅主题之间的分区分配策略。默认情况下,此参数的值为 org.apache.kafka.clients.consumer.RangeAssignor,即采用RangeAssignor分配策略。除此之外,Kafka还提供了另外两种分配策略:RoundRobinAssignor 和 StickyAssignor。消费者客户端参数 partition.assignment.strategy可以配置多个分配策略,彼此之间以逗号分隔。
RangeAssignor分配策略
RangeAssignor 分配策略的原理是按照消费者总数和分区总数进行整除运算来获得一个跨度,然后将分区按照跨度进行平均分配,以保证分区尽可能均匀地分配给所有的消费者。对于每一个主题,RangeAssignor策略会将消费组内所有订阅这个主题的消费者按照名称的字典序排序,然后为每个消费者划分固定的分区范围,如果不够平均分配,那么字典序靠前的消费者会被多分配一个分区。
RoundRobinAssignor分配策略
RoundRobinAssignor分配策略的原理是将消费组内所有消费者及消费者订阅的所有主题的分区按照字典序排序,然后通过轮询方式逐个将分区依次分配给每个消费者。RoundRobinAssignor分配策略对应的 partition.assignment.strategy 参数值为 org.apache.kafka.clients.consumer.RoundRobinAssignor。
如果同一个消费组内所有的消费者的订阅信息都是相同的,那么RoundRobinAssignor分配策略的分区分配会是均匀的。
StickyAssignor分配策略
我们再来看一下StickyAssignor分配策略,“sticky”这个单词可以翻译为“黏性的”,Kafka从0.11.x版本开始引入这种分配策略,它主要有两个目的: (1)分区的分配要尽可能均匀。 (2)分区的分配尽可能与上次分配的保持相同。 当两者发生冲突时,第一个目标优先于第二个目标。鉴于这两个目标,StickyAssignor分配策略的具体实现要比RangeAssignor和RoundRobinAssignor这两种分配策略要复杂得多。我们举例来看一下StickyAssignor分配策略的实际效果。
自定义分区分配策略
不仅可以任意选用Kafka提供的3种分配策略,还可以自定义分配策略来实现更多可选的功能。自定义的分配策略必须要实现 org.apache.kafka.clients.consumer.internals.PartitionAssignor接口。