kafka分区原则,kafka多分区消息顺序

  kafka分区原则,kafka多分区消息顺序

  00-1010背景范围分配者定义源分析场景round robin分配者定义源分析场景StickyAssignor定义场景

  

目录

卡夫卡有分区机制。创建主题时,将设置分区。如果只有一个分区,那么所有消费者都订阅这个分区消息;如果有多个分区,它们是如何在消费者中分配的?

 

  分配算法

  

背景

 

  

RangeAssignor

卡夫卡默认采用RangeAssignors分配算法。

 

  RangeAssignor策略的原理是将消费者总数和分区总数进行划分,得到一个跨度,然后根据跨度对分区进行平均划分,保证分区尽可能平均地分配给所有消费者。对于每一个话题,RangeAssignor策略都会将消费者群体中订阅该话题的所有消费者按照名字的字典顺序进行排序,然后将每个消费者划分到一个固定的划分范围内。如果它不是均匀分布的,那么具有最高字典顺序的消费者将被分配更多的分区。

  这种分发类型的明显问题是,随着消费者订阅话题数量的增加,不平衡的问题会越来越严重。对于上图中4个分区和3个用户的场景,C0将分配更多的分区。如果此时订阅另一个有4个分区的话题,C0会分配更多分区给C1和C2,这样C0总共会多分配两个分区给C1和C2,而且这种情况会随着话题的增加越来越严重。

  

定义

公共类RangeAssignor扩展AbstractPartitionAssignor {.@ Override public Map assign(Map partitions pertopic,Map subscriptions) {//1。获取每个主题有多少消费者订阅了MapString,liststring consumersuperpic=consumersuperpic(subscriptions);//2.存储最终分配案例mapstring,list string assignment=new hashmap();for(String memberId : subscriptions . keyset())assignment . put(memberId,new ArrayList());对于(图。entry topic entry : consumerspertopic . entry set()){ String topic=topic entry . getkey();list consumersForTopic=topic entry . getvalue();//3.每个主题的分区数Integer NumPartitionsfortopic=partitionspertopic . get(topic);if (numPartitionsForTopic==null)继续;collections . sort(consumersForTopic);//4.指示平均将多少个分区Int NumPartitionsSpeconsumer分配给每个使用者=numpartitionsports/consumerssports . size();//5.平均分配后,还有多少分区未分配?int ConsumersTheXTRAPATITION=numpartitionsports % consumerssports . size();list partitions=abstractpartitionassignor . partitions(topic,numPartitionsForTopic);//6.这才是重点。分配原则是将尚未平均分配给前一个消费者的分区分配给(int i=)

 

  0, n = consumersForTopic.size(); i < n; i++) { int start = numPartitionsPerConsumer * i + Math.min(i, consumersWithExtraPartition); int length = numPartitionsPerConsumer + (i + 1 > consumersWithExtraPartition ? 0 : 1); assignment.get(consumersForTopic.get(i)).addAll(partitions.subList(start, start + length)); } } return assignment; }}

 

  

 

  

 

  

场景

可以完全平均分配

 

  

 

  无法完全平均分配,排序靠前分的更多

  

 

  消费者数量大于分区数量,排名靠前先分得,排名靠后未分得分区

  

 

  

 

  

RoundRobinAssignor

定义

RoundRobinAssignor的分配策略是将消费组内订阅的所有Topic的分区及所有消费者进⾏排序后尽 量均衡的分配(RangeAssignor是针对单个Topic的分区进⾏排序分配的)。如果消费组内,消费者订阅 的Topic列表是相同的(每个消费者都订阅了相同的Topic),那么分配结果是尽量均衡的(消费者之间 分配到的分区数的差值不会超过1)。

 

  

源码分析

package org.apache.kafka.clients.consumer; public class RoundRobinAssignor extends AbstractPartitionAssignor { @Override public Map> assign(Map partitionsPerTopic, Map subscriptions) { <Map> assignment = new HashMap<>(); for (String memberId : subscriptions.keySet()) assignment.put(memberId, new ArrayList()); // 1. 环状链表,存储所有的consumer,⼀次迭代完之后⼜会回到原点 CircularIterator assigner = new CircularIterator<> (Utils.sorted(subscriptions.keySet())); // 2. 获取所有订阅的topic的partition总数 for (TopicPartition partition : allPartitionsSorted(partitionsPerTopic, subscriptions)) { final String topic = partition.topic(); while (!subscriptions.get(assigner.peek()).topics().contains(topic)) assigner.next(); assignment.get(assigner.next()).add(partition); } return assignment; } .... }

场景

无法完全平均分配,排序靠前分的更多

 

  

 

  

 

  

StickyAssignor

定义

尽管RoundRobinAssignor已经在RangeAssignor上做了⼀些优化来更均衡的分配分区,但是在⼀些情况下依旧会产⽣严重的分配偏差,从字⾯意义上看,Sticky是粘性的,可以理解为分配结果是带粘性的——每⼀次分配变更相对 上⼀次分配做最少的变动(上⼀次的结果是有粘性的) 其⽬标有两点:

 

  分区的分配尽量的均衡每⼀次重分配的结果尽量与上⼀次分配结果保持⼀致

场景

 

  到此这篇关于详解kafka中的消息分区分配算法的文章就介绍到这了,更多相关kafka消息分区分配算法内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: