持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情
kafka消费者消费分区的分配策略
独立消费者(不订阅分区)
消费者消费指定topic主题下的所有分区的数据。
在消费者 API 代码中必须配置消费者组 id。命令行启动消费者不填写消费者组id 会被自动填写随机的消费者组 id。
properties.put(ConsumerConfig.GROUP_ID_CONFIG, "test");
// 2 订阅主题 first
ArrayList<String> topics = new ArrayList<>();
topics.add("first");
kafkaConsumer.subscribe(topics);
// 3 消费数据
while (true){
ConsumerRecords<String, String> consumerRecords = kafkaConsumer.poll(Duration.ofSeconds(1));
for (ConsumerRecord<String, String> consumerRecord : consumerRecords) {
System.out.println(consumerRecord);
}
kafkaConsumer.commitAsync();
}
独立消费者(订阅分区)
通过TopicPartition对象指定消费者消费哪个topic下的哪一个分区内容。
// 组id
properties.put(ConsumerConfig.GROUP_ID_CONFIG,"test");
// 1 创建一个消费者
KafkaConsumer<String, String> kafkaConsumer = new KafkaConsumer<>(properties);
// 2 订阅主题对应的分区
ArrayList<TopicPartition> topicPartitions = new ArrayList<>();
topicPartitions.add(new TopicPartition("first",0));
kafkaConsumer.assign(topicPartitions);
// 3 消费数据
while (true){
ConsumerRecords<String, String> consumerRecords = kafkaConsumer.poll(Duration.ofSeconds(1));
for (ConsumerRecord<String, String> consumerRecord : consumerRecords) {
System.out.println(consumerRecord);
}
}
消费者组
创建三个消费者,设置他们的组id相同,他们就会自动归档到一个消费者,然后通过消费者的方式进行消费。
分区的分配以及再平衡
一个消费者组由多个消费者组成,一个主题由多个分区组成,如何来保证哪个消费者消费哪个分区的数据。
kafka的主流分区分配有:Range、RoundRobin、Sticky、CooperativeSticky。 可以通过配置参数partition.assignment.strategy,修改分区的分配策略。默认策略是Range + CooperativeSticky。Kafka可以同时使用多个分区分配策略。
Range分区再平衡
1、Range是针对与每一个topic来讲。
2、首先会对topic按照分区序号排序和对消费者按照字母顺序排序。
3、用分区数/消费者数来决定每个消费者应该消费几个分区。如果除不尽前面的几个消费者会分别多多消费一个分区。
4、如果topic的数量过多,除不尽的情况也比较多,那么排序在前面的消费者会消费更多的分区,造成数据倾斜。
例如,7/3 = 2 余 1 ,除不尽,那么 消费者 C0 便会多消费 1 个分区。 C0消费0,1,2分区,C1消费3,4分区,C2消费5,6分区。8/3=2余2,除不尽,那么C0和C1分别多消费一个。顺序固定。
停掉消费者C0,在45秒内再次发送消息,C0消费者的任务会被整体的划分到1号消费者或者2号消费者。
原因:每个消费者都会和coordinator保持心跳(默认3s),一旦超时(session.timeout.ms=45s),该消费者会被移除,并触发再平衡;或者消费者处理消息的过长(max.poll.interval.ms5分钟),也会触发再平衡。
45秒后再次发送消息:会触发再平衡策略即1号消费者消费:0,1,2,3;2号消费者消费4,5,6
RoundRobin分区再平衡
1、RoundRobin是针对所有的topic来讲。
2、把所有的topic的分区和消费者都列出来,根据hashCode排序。最后采用轮询的方式把分区分配到具体的消费者。
停掉消费者C0,在45秒内再次发送消息,把数据轮询分成 0 、6 和 3 号分区数据,分别由 1 号消费者或者 2 号消费者消费。(不是整体给某一个消费者)
当C0退出后,会再次轮询分配即0号分区给1号消费者,3号分区给2号消费者,6号分区给再给一号消费者。
45秒后再次发送消息:会触发再平衡策略即1号消费者消费:0,2,4,6;2号消费者消费1,3,5.
Sticky 以及再平衡
粘性分区是再执行分区分配时候会考虑前一次的分配结果,尽量少的调整分配的变动,来节省开销。
例如:七个分区、三个消费者。
均匀随机的消费:7处于3等于2余数1,则每一个会尽量分配两个,然后还有一个会多个分区消费。
比如有两个消费者消费两个分区:但是他们每次启动消费的分区数都不相同,与Range不同的时每次消费的都随机。
一开始
C0:0,1;
C1:2,5,3;
C2:4,6
停掉消费者C0,在45秒内再次发送消息,把数据轮询分成0,1 号分区数据,分别由 1 号消费者或者 2 号消费者消费。(不是整体给某一个消费者)。
当C0退出后C1多消费10号分区,C2多消费1号分区。
45秒后再次发送消息:会触发再平衡策略即1号消费者消费:2、3、5;2号消费者消费0、1、4、6。