kafka 原理深度剖析系列|分区分配策略

在上一篇文章中,我们为大家详细介绍可 Kafka 的原理与核心概念,包括控制器选举及恢复、分区 leader 的选举等,本次我们来为大家详细讲解 Kafka 等分区分配策略,希望能对大家有所帮助

Kafka 提供了消费者客户端参数 partition.assignment.strategy⽤来设置消费者与订阅主题之间的分区分配策略。默认情况下此参数的值为:org.apache.kafka.clients.consumer.RangeAssignor,即采⽤ RangeAssignor 分配策略。除此之外,Kafka 中还提供了另外两种分配策略: RoundRobinAssignor 和 StickyAssignor。消费者客户端参数 partition.asssignment.strategy 可以配置多个分配策略,彼此之间以逗号分隔。

RangeAssignor 分配策略

RangeAssignor 策略的原理是按照消费者总数和分区总数进⾏整除运算来获得⼀个跨度,然后将分区按照跨度进⾏平均分配,以保证分区尽可能均匀地分配给所有的消费者。对于每⼀个 topic,

RangeAssignor 策略会将消费组内所有订阅这个 topic 的消费者按照名称的字典序排序,然后为每个消费者划分固定的分区范围,如果不够平均分配,那么字典序靠前的消费者会被多分配⼀个分区。

假设 n=分区数/消费者数量,m=分区数 %消费者数量,那么前 m 个消费者每个分配 n+1 个分区,后⾯的(消费者数量-m)个消费者每个分配 n 个分区。如果消费组内有 2 个消费者 C0 和 C1,且都订阅了主题 t0 和 t1,并且每个主题都有 4 个分区,那么所订阅的所 有分区可以标识为:t0p0、t0p1、t0p2、t0p3、t1p0、t1p1、t1p2、t1p3。最终的分配结果为:

消费者C0:t0p0、t0p1、t1p0、t1p1 消费者C1:t0p2、t0p3、t1p2、t1p3

这样分配的很均匀,那么此种分配策略能够⼀直保持这种良好的特性呢?我们再来看下另外⼀种情况。 假设上⾯例⼦中 2 个主题都只有 3 个分区,那么所订阅的所有分区可以标识为:t0p0、t0p1、t0p2、 t1p0、t1p1、t1p2。最终的分配结果为:

消费者C0:t0p0、t0p1、t1p0、t1p1 消费者C1:t0p2、t1p2
可以明显的看到这样的分配并不均匀,如果将类似的情形扩⼤,有可能会出现部分消费者过载的情况

RoundRobinAssignor 分配策略

RoundRobinAssignor 策略的原理是将消费组内所有消费者以及消费者所订阅的所有 topic 的 partition 按照字典序排序,然后通过轮询⽅式逐个将分区以此分配给每个消费者。RoundRobinAssignor 策略对应的 partition.assignment.strategy 参数值为:org.apache.kafka.clients.consumer.RoundRobinAssignor。

如果同⼀个消费组内所有的消费者的订阅信息都是相同的,那么 RoundRobinAssignor 策略的分区分配 会是均匀的。假设消费组中有 2 个消费者 C0 和 C1,都订阅了主题 t0 和 t1,并且每个主题都有 3 个分区,那么所订阅的所 有分区可以标识为:t0p0、t0p1、t0p2、t1p0、t1p1、t1p2。最终的分配结果为:

消费者C0:t0p0、t0p2、t1p1 消费者C1:t0p1、t1p0、t1p2

如果同⼀个消费组内的消费者所订阅的信息是不相同的,那么在执⾏分区分配的时候就不是完全的轮询分配,有可能会导致分区分配的不均匀。如果某个消费者没有订阅消费组内的某个 topic,那么在分配分区的时候此消费者将分配不到这个 topic 的任何分区。

假设消费组内有 3 个消费者 C0、C1 和 C2,它们共订阅了 3 个主题:t0、t1、t2,这 3 个主题分别有 1、2、3 个分区,即整个消费组订阅了 t0p0、t1p0、t1p1、t2p0、t2p1、t2p2 这 6 个分区。具体⽽⾔,消费者 C0 订阅的是主题 t0,消费者 C1 订阅的是主题 t0 和 t1,消费者 C2 订阅的是主题 t0、t1 和 t2,那么最终的分配结果为:

消费者C0:t0p0 消费者C1:t1p0 消费者C2:t1p1、t2p0、t2p1、t2p2

StickyAssignor 分配策略

Kafka 从 0.11.x 版本开始引⼊这种分配策略,它主要有两个⽬的:

  • 分区的分配要尽可能的均匀;

  • 分区的分配尽可能的与上次分配的保持相同。

当两者发⽣冲突时,第⼀个⽬标优先于第⼆个⽬标。鉴于这两个⽬标,StickyAssignor 策略的具体 实现要⽐RangeAssignor 和 RoundRobinAssignor 这两种分配策略要复杂很多。

假设消费组内有 3 个消费者:C0、C1 和 C2,它们都订阅了 4 个主题:t0、t1、t2、t3,并且每个主题有 2 个分区,也就是说整个消费组订阅了 t0p0、t0p1、t1p0、t1p1、t2p0、t2p1、t3p0、t3p1 这 8 个分区。 最终的分配结果如下

消费者C0:t0p0、t1p1、t3p0 消费者C1:t0p1、t2p0、t3p1 消费者C2:t1p0、t2p1

这样初看上去似乎与采⽤RoundRobinAssignor 策略所分配的结果相同,但事实是否真的如此呢?再假 设此时消费者 C1 脱离了消费组,那么消费组就会执⾏再平衡操作,进⽽消费分区会重新分配。如果采⽤ RoundRobinAssignor 策略,那么此时的分配结果如下:

消费者C0:t0p0、t1p0、t2p0、t3p0 消费者C2:t0p1、t1p1、t2p1、t3p1

如分配结果所示,RoundRobinAssignor 策略会按照消费者 C0 和 C2 进⾏重新轮询分配。⽽如果此时使⽤ 的是 StickyAssignor 策略,那么分配结果为:

消费者C0:t0p0、t1p1、t3p0、t2p0 消费者C2:t1p0、t2p1、t0p1、t3p1

可以看到分配结果中保留了上⼀次分配中对于消费者 C0 和 C2 的所有分配结果,并将原来消费者 C1 的“负 担”分配给了剩余的两个消费者 C0 和 C2,最终 C0 和 C2 的分配还保持了均衡。

如果发⽣分区重分配,那么对于同⼀个分区⽽⾔有可能之前的消费者和新指派的消费者不是同⼀个,对 于之前消费者进⾏到⼀半的处理还要在新指派的消费者中再次复现⼀遍,这显然很浪费系统资源。

StickyAssignor 策略如同其名称中的“sticky”⼀样,让分配策略具备⼀定的“粘性”,尽可能地让前后两次分 配相同,进⽽减少系统资源的损耗以及其它异常情况的发⽣。

例如消费组内有 3 个消费者:C0、C1 和 C2,集群中有 3 个主题:t0、t1 和 t2,这 3 个主题分别有 1、2、3 个分区,也就是说集群中有 t0p0、t1p0、t1p1、t2p0、t2p1、t2p2 这 6 个分区。消费者 C0 订阅了主题 t0,消费者 C1 订阅了主题 t0 和 t1,消费者 C2 订阅了主题 t0、t1 和 t2。如果此时采⽤RoundRobinAssignor 策略,那么最终的分配结果如下所示:

消费者C0:t0p0 消费者C1:t1p0 消费者C2:t1p1、t2p0、t2p1、t2p2

如果此时采⽤的是 StickyAssignor 策略,那么最终的分配结果为:

消费者C0:t0p0 消费者C1:t1p0、t1p1 消费者C2:t2p0、t2p1、t2p2

这是⼀个最优解(消费者 C0 没有订阅主题 t1 和 t2,所以不能分配主题 t1 和 t2 中的任何分区给 它,对于消费者 C1 也可同理推断)。假如此时消费者 C0 脱离了消费组,那么 RoundRobinAssignor 策略的分配结果为:

消费者C1:t0p0、t1p1 消费者C2:t1p0、t2p0、t2p1、t2p2

RoundRobinAssignor 策略保留了消费者 C1 和 C2 中原有的 3 个分区的分配:t2p0、t2p1 和 t2p2(针对结果集 1)。⽽如果采⽤的是 StickyAssignor 策略,那么分配结果为:

消费者C1:t1p0、t1p1、t0p0 消费者C2:t2p0、t2p1、t2p2

StickyAssignor 策略保留了消费者 C1 和 C2 中原有的 5 个分区的分配:t1p0、t1p1、t2p0、 t2p1、t2p2。

Kafka 分区分配策略我们就说到这里,下一篇文章,我们将给大家带来 Kafka 调优指南。


 写在最后

近年来,在AIOps领域快速发展的背景下,IT工具、平台能力、解决方案、AI场景及可用数据集的迫切需求在各行业迸发。基于此,云智慧在2021年8月发布了AIOps社区,旨在树起一面开源旗帜,为各行业客户、用户、研究者和开发者们构建活跃的用户及开发者社区,共同贡献及解决行业难题、促进该领域技术发展。

社区先后开源了数据可视化编排平台-FlyFish、运维管理平台OMP、云服务管理平台-摩尔平台、Hours算法等产品。

可视化编排平台-FlyFish:

项目介绍:https://www.cloudwise.ai/flyFish.html

Github地址: https://github.com/CloudWise-OpenSource/FlyFish

Gitee地址: https://gitee.com/CloudWise/fly-fish

行业案例:https://www.bilibili.com/video/BV1z44y1n77Y/

部分大屏案例:

你可能感兴趣的:(技术干货,kafka,java,big,data,架构,消息队列)