当前位置: 首页 > 后端技术 > Java

Kafka分区分配策略

时间:2023-04-02 10:31:05 Java

上一篇我们详细介绍了Kafka的原理和核心概念,包括controller选举和回收,partitionleader选举等,具体见Kafka核心技术概念和架构原理,本次我们将详细讲解Kafka和其他分区分配策略,希望对您有所帮助。Kafka提供消费者客户端参数partition.assignment.strategy来设置消费者与订阅主题之间的分区分配策略。默认情况下,该参数的值为:org.apache.kafka.clients.consumer.RangeAssignor,即采用RangeAssignor分配策略。此外,Kafka还提供了另外两种分配策略:RoundRobinAssignor和StickyAssignor。consumer客户端参数partition.assignment.strategy可以配置多个分配策略,以逗号分隔。RangeAssignor分配策略RangeAssignor策略的原理是将消费者总数与分区总数相除得到一个span,然后根据span均匀分配分区,保证分区尽可能均匀地分配给所有消费者尽可能。对于每一个topic,RangeAssignor策略会按照name的字典序对consumergroup中所有订阅该topic的消费者进行排序,然后为每个consumer划分一个固定的partitionrange。如果分布不够均匀,那么再分配一个partition给toplexicographicalConsumer。假设n=分区数/消费者数,m=分区数%消费者数,则前m个消费者各分配n+1个分区,后面(消费者数-m)个消费者各分配n个分区。如果消费者组中有2个消费者C0和C1,他们都订阅了主题t0和t1,每个主题有4个分区,那么订阅的所有分区可以标识为:t0p0、t0p1、t0p2、t0p3、t1p0、t1p1、t1p2、t1p3。最终的分配结果为:ConsumerC0:t0p0,t0p1,t1p0,t1p1ConsumerC1:t0p2,t0p3,t1p2,t1p3分布很均匀,那么这种分布策略能不能一直保持这种好的特性呢?再来看另一种情况。假设上面例子中的两个主题只有三个分区,那么订阅的所有分区可以标识为:t0p0,t0p1,t0p2,t1p0,t1p1,t1p2。最终的分配结果为:ConsumerC0:t0p0,t0p1,t1p0,t1p1ConsumerC1:t0p2,t1p2可以明显看出分布不均匀。如果类似的情况扩大,可能会发生一些消费RoundRobinAssignor分配策略的原理RoundRobinAssignor策略是将消费者组中所有消费者的分区和消费者订阅的所有主题按照字典顺序排序,然后将分区分配给每个消费者一个一个通过轮询通过。RoundRobinAssignor策略对应的partition.assignment.strategy参数值为:org.apache.kafka.clients.consumer.RoundRobinAssignor。如果同一个消费者组中所有消费者的订阅信息都相同,那么RoundRobinAssignor策略的分区分配会是偶数。假设消费者组中有两个消费者C0和C1,都订阅了topict0和t1,每个topic有3个partition,那么所有订阅的partition可以标识为:t0p0,t0p1,t0p2,t1p0,t1p1,t1p2.最终分配结果为:ConsumerC0:t0p0,t0p2,t1p1ConsumerC1:t0p1,t1p0,t1p2有时不是完全循环分配,可能会导致分区分配不均。如果消费者没有订阅消费组中的某个主题,则在分配分区时不会为该消费者分配该主题的任何分区。假设消费组中有3个消费者C0、C1、C2,订阅了3个主题:t0、t1、t2。这3个主题分别有1、2、3个分区,即整个消费组订阅了t0p0、t1p0、t1p1、t2p0、t2p1、t2p2这六个分区。具体来说,消费者C0订阅主题t0,消费者C1订阅主题t0和t1,消费者C2订阅主题t0、t1和t2,那么最终的分发结果为:消费者C0:t0p0消费消费者C1:t1p0消费者C2:t1p1,t2p0,t2p1,t2p2StickyAssignor分配策略Kafka从0.11版本开始就引入了这种分配策略。分配尽可能接近上次分配。当两者发生冲突时,第一个目标优先于第二个目标。鉴于这两个目标,StickyAssignor策略的具体实现要比RangeAssignor和RoundRobinAssignor这两种分配策略复杂得多。假设消费组中有3个消费者:C0、C1、C2,他们都订阅了4个主题:t0、t1、t2、t3,每个主题有2个partition,也就是说整个消费组订阅了t0p0,t0p1,t1p0,t1p1,t2p0,t2p1,t3p0,t3p1这8个分区。最终的分配结果如下ConsumerC0:t0p0,t1p1,t3p0ConsumerC1:t0p1,t2p0,t3p1ConsumerC2:t1p0,t2p1乍一看好像和RoundRobinAssignor策略分配的结果一样,但是是不是真的?所以?假设此时消费者C1离开了消费组,那么消费组会进行一次重平衡操作,然后消费分区会被重新分配。如果采用RoundRobinAssignor策略,此时的分配结果如下:ConsumerC0:t0p0,t1p0,t2p0,t3p0ConsumerC2:t0p1,t1p1,t2p1,t3p1C2进行重新轮询分配。而此时如果使用StickyAssignor策略,则赋值结果为:ConsumerC0:t0p0,t1p1,t3p0,t2p0ConsumerC2:t1p0,t2p1,t0p1,t3p1可以看到赋值结果中保留了上一次赋值的All中间消费者C0和C2的分配结果,原消费者C1的“负担”分配给剩下的两个消费者C0和C2,最终C0和C2的分配保持平衡。如果发生partitionreallocation,那么对于同一个partition,有可能之前的consumer和新分配的consumer不是同一个。这显然是对系统资源的浪费。StickyAssignor策略,正如其名字中的“粘性”一样,使分配策略具有一定的“粘性”,使两次分配尽可能相同,从而减少系统资源的损失和其他异常的发生情况。例如,消费组中有3个消费者:C0、C1、C2,集群中有3个主题:t0、t1、t2。这3个topic分别有1、2、3个分区,也就是说集群中有t0p0,t1p0,t1p1,t2p0,t2p1,t2p2这六个分区。消费者C0订阅了主题t0,消费者C1订阅了主题t0??和t1,消费者C2订阅了主题t0、t1和t2。如果此时采用RoundRobinAssignor策略,最终的分配结果如下:ConsumerC0:t0p0ConsumerC1:t1p0ConsumerC2:t1p1,t2p0,t2p1,t2p2如果此时采用StickyAssignor策略,最终的分配结果为:ConsumerC0:t0p0ConsumerC1:t1p0,t1p1ConsumerC2:t2p0,t2p1,t2p2这是一个最优解(ConsumerC0没有订阅topict1和t2,所以不能分配topict1和t2t2中的任何partition对它来说,同样可以推断出消费者C1)。如果此时消费者C0离开消费者组,则RoundRobinAssignor策略的分配结果为:ConsumerC1:t0p0,t1p1ConsumerC2:t1p0,t2p0,t2p1,t2p2RoundRobinAssignor策略保留了原来消费者C1和C2的三个分配分区:t2p0、t2p1和t2p2(对于结果集1)。如果采用StickyAssignor策略,则分配结果为:ConsumerC1:t1p0,t1p1,t0p0ConsumerC2:t2p0,t2p1,t2p2StickyAssignor策略保留了consumerC1和C2中5个分区的原始分配:t1p0,t1p1,t2p0,t2p1,t2p2。这就是Kafka分区分配策略的全部内容。下一篇文章,我们将为大家带来一份Kafka调优指南。写在最后近年来,在AIOps领域高速发展的背景下,各行业对IT工具、平台能力、解决方案、AI场景和可用数据集的迫切需求呈爆发式增长。基于此,云智于2021年8月发布了AIOps社区,旨在竖起开源大旗,为各行业的客户、用户、研究人员和开发者打造一个活跃的用户和开发者社区,共同贡献和解决行业问题。问题,促进该领域的技术发展。社区先后开源了数据可视化与编排平台——FlyFish、运维管理平台OMP、云服务管理平台——Moore平台、Hours算法等产品。视觉编排平台-FlyFish:项目介绍:https://www.cloudwise.ai/flyF...Github地址:https://github.com/CloudWise-...Gitee地址:https://gitee.com/CloudWise/f...行业案例:https://www.bilibili.com/vide...部分大屏案例:可添加小助手(xiaoyuerwie)注:飞鱼。加入开发者交流群,与行业大咖1V1交流!您还可以通过小助手获取云智慧AIOps信息,了解飞鱼的最新进展!