资阳住房和城乡建设厅官方网站,查域名138,北京网站建设 一流,酒店网站制作Kafka消费分组#xff0c;消息消费原理
同一个消费组里的消费者不能消费同一个分区#xff0c;不同消费组的消费组可以消费同一个分区 #xff08;即同一个消费组里面的消费者只能在一个分区中#xff09;
Kafka分区分配策略
问题
用过 Kafka 的同学用过都知道#xf…Kafka消费分组消息消费原理
同一个消费组里的消费者不能消费同一个分区不同消费组的消费组可以消费同一个分区 即同一个消费组里面的消费者只能在一个分区中
Kafka分区分配策略
问题
用过 Kafka 的同学用过都知道每个 Topic 一般会有很多个 partitions。为了使得我们能够及时消费消息我们也可能会启动多个 Consumer 去消费而每个 Consumer 又会启动一个或多个streams去分别消费 Topic 里面的数据。我们又知道Kafka 存在 Consumer Group 的概念也就是 group.id 一样的 Consumer这些 Consumer 属于同一个Consumer Group组内的所有消费者协调在一起来消费订阅主题(subscribed topics)的所有分区(partition)。当然每个分区只能由同一个消费组内的一个consumer来消费。那么问题来了同一个 Consumer Group 里面的 Consumer 是如何知道该消费哪些分区里面的数据呢
在 Kafka 内部存在两种默认的分区分配策略Range轮循分配 和 RoundRobin范围策略。当以下事件发生时Kafka 将会进行一次分区分配
同一个 Consumer Group 内新增消费者 消费者离开当前所属的Consumer Group包括shuts down 或 crashes订阅的主题新增分区 将分区的所有权从一个消费者移到另一个消费者称为重新平衡rebalance如何rebalance就涉及到本文提到的分区分配策略。下面我们将详细介绍 Kafka 内置的两种分区分配策略。
RoundRobin轮循分配 这个分区分配策略简单来说就是列出所有的分区然后和消费线程之间进行循环的分配即可。
如果你需要使用该分配策略你需要满足所有的消费线程都是消费相同的topic且每个消费者之间的消费线程数是一样的。
Range策略是对每个主题而言的首先对同一个主题里面的分区按照序号进行排序并对消费者按照字母顺序进行排序。在我们的例子里面排完序的分区将会是0, 1, 2, 3, 4, 5, 6, 7, 8, 9消费者线程排完序将会是C1-0, C2-0, C2-1。然后将partitions的个数除于消费者线程的总数来决定每个消费者线程消费几个分区。如果除不尽那么前面几个消费者线程将会多消费一个分区。在我们的例子里面我们有10个分区3个消费者线程 10 / 3 3而且除不尽那么消费者线程 C1-0 将会多消费一个分区所以最后分区分配的结果看起来是这样的
C1-0 将消费 0, 1, 2, 3 分区
C2-0 将消费 4, 5, 6 分区
C2-1 将消费 7, 8, 9 分区假如我们有11个分区那么最后分区分配的结果看起来是这样的
C1-0 将消费 0, 1, 2, 3 分区
C2-0 将消费 4, 5, 6, 7 分区
C2-1 将消费 8, 9, 10 分区假如我们有2个主题(T1和T2)分别有10个分区那么最后分区分配的结果看起来是这样的
C1-0 将消费 T1主题的 0, 1, 2, 3 分区以及 T2主题的 0, 1, 2, 3分区
C2-0 将消费 T1主题的 4, 5, 6 分区以及 T2主题的 4, 5, 6分区
C2-1 将消费 T1主题的 7, 8, 9 分区以及 T2主题的 7, 8, 9分区可以看出C1-0 消费者线程比其他消费者线程多消费了2个分区这就是Range strategy的一个很明显的弊端。
Range范围策略 述简单来说就是分区总数/消费线程数如果有余则表明有的消费线程之间分配的分区不均匀那么这个多出来的分区会给前几个消费线程处理。
比如上述5个分区2个comsumer,4个消费线程则5/41这个表明如果4个消费线程均分5个分区还会多出一个分区
那么这个多出的额外分区就会给前面的消费线程处理所以它会把第一个分区先给到c1-0消费线程消费。
也可以这样的认为分配
5/4余1则分配规则为2,1,1,1对应的消费线程为C1-0,C1-1,C2-0,C2-1
如果是6个分区的话
6/4余2则分配规则为2,2,1,1对应的消费线程为C1-0,C1-1,C2-0,C2-1
使用RoundRobin策略有两个前提条件必须满足
同一个Consumer Group里面的所有消费者的num.streams必须相等每个消费者订阅的主题必须相同。
所以这里假设前面提到的2个消费者的num.streams 2。RoundRobin策略的工作原理将所有主题的分区组成 TopicAndPartition 列表然后对 TopicAndPartition 列表按照 hashCode 进行排序这里文字可能说不清看下面的代码应该会明白
val allTopicPartitions ctx.partitionsForTopic.flatMap { case(topic, partitions) info(Consumer %s rebalancing the following partitions for topic %s: %s.format(ctx.consumerId, topic, partitions))partitions.map(partition {TopicAndPartition(topic, partition)})
}.toSeq.sortWith((topicPartition1, topicPartition2) {/** Randomize the order by taking the hashcode to reduce the likelihood of all partitions of a given topic ending* up on one consumer (if it has a high enough stream count).*/topicPartition1.toString.hashCode topicPartition2.toString.hashCode
})最后按照round-robin风格将分区分别分配给不同的消费者线程。
在我们的例子里面加入按照 hashCode 排序完的topic-partitions组依次为T1-5, T1-3, T1-0, T1-8, T1-2, T1-1, T1-4, T1-7, T1-6, T1-9我们的消费者线程排序为C1-0, C1-1, C2-0, C2-1最后分区分配的结果为
C1-0 将消费 T1-5, T1-2, T1-6 分区
C1-1 将消费 T1-3, T1-1, T1-9 分区
C2-0 将消费 T1-0, T1-4 分区
C2-1 将消费 T1-8, T1-7 分区多个主题的分区分配和单个主题类似这里就不在介绍了。
根据上面的详细介绍相信大家已经对Kafka的分区分配策略原理很清楚了。不过遗憾的是目前我们还不能自定义分区分配策略只能通过partition.assignment.strategy参数选择 range 或 roundrobin。partition.assignment.strategy参数默认的值是range。