目录
- 一、RoundRobin 分区分配策略原理
- 二、RoundRobin分区分配策略代码案例
- 2.1、创建带有7个分区的sixTopic主题
- 2.3、创建三个消费者 组成 消费者组
- 2.3、创建生产者
- 2.4、测试
- 2.5、RoundRobin分区分配策略代码案例说明
- 三、RoundRobin 分区分配再平衡案例
- 3.1、停止某一个消费者后,(45s 以内)重新发送消息示例
- 3.2、停止某一个消费者后,(45s 以后)重新发送消息示例
- 3.3、RoundRobin 分区分配再平衡案例说明
一、RoundRobin 分区分配策略原理
- RoundRobin 针对集群中所有Topic而言。
- RoundRobin 轮询分区策略,是把所有的 partition 和所有的consumer 都列出来,然后按照 hashcode 进行排序,最后通过轮询算法来分配 partition 给到各个消费者。
二、RoundRobin分区分配策略代码案例
2.1、创建带有7个分区的sixTopic主题
-
在 Kafka 集群控制台,创建带有7个分区的sixTopic主题
bin/kafka-topics.sh --bootstrap-server 192.168.136.27:9092 --create --partitions 7 --replication-factor 1 --topic sixTopic
2.3、创建三个消费者 组成 消费者组
-
复制 CustomConsumer1类,创建 CustomConsumer2和CustomConsumer3。这样可以由三个消费者组成消费者组,组名都为“test1”,设置分区分配策略为 RoundRobin。
package com.xz.kafka.consumer; import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecords; import org.apache.kafka.clients.consumer.KafkaConsumer; import org.apache.kafka.common.serialization.StringDeserializer; import java.time.Duration; import java.util.ArrayList; import java.util.Properties; public class CustomConsumer1 { public static void main(String[] args) { // 0 配置 Properties properties = new Properties(); // 连接 bootstrap.servers properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"192.168.136.27:9092,192.168.136.28:9092,192.168.136.29:9092"); // 反序列化 properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); // 配置消费者组id properties.put(ConsumerConfig.GROUP_ID_CONFIG,"test1"); // 设置分区分配策略 properties.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,"org.apache.kafka.clients.consumer.RoundRobinAssignor"); // 1 创建一个消费者 "", "hello" KafkaConsumer<String, String> kafkaConsumer = new KafkaConsumer<>(properties); // 2 订阅主题 sixTopic ArrayList<String> topics = new ArrayList<>(); topics.add("sixTopic"); 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); } } } }
2.3、创建生产者
-
创建CustomProducer生产者。
package com.xz.kafka.producer; import org.apache.kafka.clients.producer.*; import org.apache.kafka.common.serialization.StringSerializer; import java.util.Properties; public class CustomProducerCallback { public static void main(String[] args) throws InterruptedException { //1、创建 kafka 生产者的配置对象 Properties properties = new Properties(); //2、给 kafka 配置对象添加配置信息:bootstrap.servers properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"192.168.136.27:9092,192.168.136.28:9092,192.168.136.29:9092"); //3、指定对应的key和value的序列化类型 key.serializer value.serializer properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName()); //4、创建 kafka 生产者对象 KafkaProducer<String, String> kafkaProducer = new KafkaProducer<>(properties); //5、调用 send 方法,发送消息 for (int i = 0; i < 200; i++) { kafkaProducer.send(new ProducerRecord<>("sixTopic", "hello kafka" + i), new Callback() { @Override public void onCompletion(RecordMetadata metadata, Exception exception) { if (exception == null){ System.out.println("主题: "+metadata.topic() + " 分区: "+ metadata.partition()); } } }); Thread.sleep(2); } // 3 关闭资源 kafkaProducer.close(); } }
2.4、测试
-
首先,在 IDEA中分别启动消费者1、消费者2和消费者3代码
-
然后,在 IDEA中分别启动生产者代码
-
在 IDEA 控制台观察消费者1、消费者2和消费者3控制台接收到的数据,如下图所示:
2.5、RoundRobin分区分配策略代码案例说明
- 由上述测试输出结果截图可知: 消费者1消费1、4分区的数据;消费者2消费2和5分区的数据;消费者3消费0、3、6分区的数据。
- 说明:Kafka 采用修改后的RoundRobin分区分配策略。
三、RoundRobin 分区分配再平衡案例
3.1、停止某一个消费者后,(45s 以内)重新发送消息示例
- 由下图控制台输出可知:2号消费者 消费到 2、5号分区数据。
- 由下图控制台输出可知:3号消费者 消费到 0、3、6号分区数据。
3.2、停止某一个消费者后,(45s 以后)重新发送消息示例
-
由下图控制台输出可知:2号消费者 消费到 1、3、5号分区数据。
-
由下图控制台输出可知:3号消费者 消费到 0、2、4、6号分区数据。
3.3、RoundRobin 分区分配再平衡案例说明
- 1号消费者挂掉后,消费者组需要按照超时时间 45s 来判断它是否退出,所以需要等待,时间到了 45s 后,判断它真的退出就会把任务分配给其他 broker 执行。
- 消费者 1 已经被踢出消费者组,所以重新按照 RoundRobin 方式分配。