Kafka3.0.0版本——消费者(RoundRobin分区分配策略以及再平衡)

目录

    • [一、RoundRobin 分区分配策略原理](#一、RoundRobin 分区分配策略原理)
    • 二、RoundRobin分区分配策略代码案例
    • [三、RoundRobin 分区分配再平衡案例](#三、RoundRobin 分区分配再平衡案例)
      • [3.1、停止某一个消费者后,(45s 以内)重新发送消息示例](#3.1、停止某一个消费者后,(45s 以内)重新发送消息示例)
      • [3.2、停止某一个消费者后,(45s 以后)重新发送消息示例](#3.2、停止某一个消费者后,(45s 以后)重新发送消息示例)
      • [3.3、RoundRobin 分区分配再平衡案例说明](#3.3、RoundRobin 分区分配再平衡案例说明)

一、RoundRobin 分区分配策略原理

  • RoundRobin 针对集群中所有Topic而言。
  • RoundRobin 轮询分区策略,是把所有的 partition 和所有的consumer 都列出来,然后按照 hashcode 进行排序,最后通过轮询算法来分配 partition 给到各个消费者。

二、RoundRobin分区分配策略代码案例

2.1、创建带有7个分区的sixTopic主题

  • 在 Kafka 集群控制台,创建带有7个分区的sixTopic主题

    java 复制代码
    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。

    java 复制代码
    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生产者。

    java 复制代码
    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 方式分配。
相关推荐
Mr.朱鹏8 小时前
SQL深度分页问题案例实战
java·数据库·spring boot·sql·spring·spring cloud·kafka
山沐与山17 小时前
【MQ】Kafka与RocketMQ深度对比
分布式·kafka·rocketmq
yumgpkpm19 小时前
Cloudera CDP7、CDH5、CDH6 在华为鲲鹏 ARM 麒麟KylinOS做到无缝切换平缓迁移过程
大数据·arm开发·华为·flink·spark·kafka·cloudera
树下水月19 小时前
Easyoole 使用rdkafka 进行kafka的创建topic创建 删除 以及数据发布 订阅
分布式·kafka
Cat God 00720 小时前
基于Docker搭建kafka集群
docker·容器·kafka
Cat God 00720 小时前
基于 Docker 部署 Kafka(KRaft + SASL/PLAIN 认证)
docker·容器·kafka
KD1 天前
设计模式——责任链模式实战,优雅处理Kafka消息
后端·设计模式·kafka
原神启动12 天前
Kafka详解
分布式·kafka
一只懒鱼a2 天前
搭建kafka集群(安装包 + docker方式)
运维·容器·kafka
青春不流名2 天前
如何在Kafka中使用SSL/TLS证书认证
分布式·kafka·ssl