Kafka多个消费者监听消费同一个Topic主题

一、需求介绍

有一个Topic:hw_data 有3个分区 3个副本
组:hw-data-group
将这个主题的消息分发给两个(或者多个)消费者消费,(不能消费相同的消息)

在这里插入图片描述

二、@kafkaListener注解

在这里插入图片描述

@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE })

@Retention(RetentionPolicy.RUNTIME)

@MessageMapping

@Documented

@Repeatable(KafkaListeners.class)

public @interface KafkaListener {

   /**
    * 消费者的id,当GroupId没有被配置的时候,默认id为GroupId
    */
   String id() default "";

   /**
    * 监听容器工厂,当监听时需要区分单数据还是多数据消费需要配置containerFactory      属性
    */
   String containerFactory() default "";

   /**
    * 需要监听的Topic,可监听多个,和 topicPattern 属性互斥
	*/
   String[] topics() default {};

   /**
    * 需要监听的Topic的正则表达。和 topics,topicPartitions属性互斥
    */
   String topicPattern() default "";


   /**
    * 可配置更加详细的监听信息,必须监听某个Topic中的指定分区,或者从offset为200的偏移量开始监听,可配置该参数, 和 topicPattern 属性互斥
    */
   TopicPartition[] topicPartitions() default {};

   /**
    *侦听器容器组 
    */
   String containerGroup() default "";

   /**
    * 监听异常处理器,配置BeanName
    */
   String errorHandler() default "";


   /**
    * 消费组ID 
    */
   String groupId() default "";

   /**
    * id是否为GroupId
    */
   boolean idIsGroup() default true;

   /**
    * 消费者Id前缀
    */
   String clientIdPrefix() default "";
   
   /**
    * 真实监听容器的BeanName,需要在 BeanName前加 "__"
    */
   String beanRef() default "__listener";
}

三、代码实现

3.1 第一个消费者

package com.dataWarehouseOss.consumer;

import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.annotation.TopicPartition;
import org.springframework.stereotype.Component;

/**
 * @author :LiuShihao
 * @date :Created in 2020/9/16 4:15 下午
 * @desc :
 * containerGroup:侦听器容器组
 * topicPartitions:可配置更加详细的监听信息,必须监听某个Topic中的指定分区,或者从offset为200的偏移量开始监听,可配置该参数, 和 topicPattern 属性互斥
 */
@Slf4j
@Component
public class Consumer1 {
    @KafkaListener(containerGroup="first-group",topicPartitions = {@TopicPartition(topic = "first",partitions = {"0","1"})})
    public void m1(ConsumerRecord<String, String> record){
        log.info("分区0,1 :"+record.topic()+" : "+record.value());
    }
}

3.2 第二个消费者

package com.dataWarehouseOss.consumer;

import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.annotation.TopicPartition;
import org.springframework.stereotype.Component;

/**
 * @author :LiuShihao
 * @date :Created in 2020/9/16 4:15 下午
 * @desc :
 * containerGroup:侦听器容器组
 * topicPartitions:可配置更加详细的监听信息,必须监听某个Topic中的指定分区,或者从offset为200的偏移量开始监听,可配置该参数, 和 topicPattern 属性互斥
 */
@Slf4j
@Component
public class Consumer2 {
    @KafkaListener(containerGroup="first-group",topicPartitions = {@TopicPartition(topic = "first",partitions = {"2"})})
    public void m1(ConsumerRecord<String, String> record){
        log.info("分区2 :"+record.topic()+" : "+record.value());
    }
}

3.3 生产者

@Component
@Slf4j
public class SendKafkaToFirst {
    @Autowired
    KafkaTemplate kafkaTemplate;
    public static final String  TOPIC = "first";
    @Scheduled(cron = "0 */2 * * * ?")
    public void sendKafka(){
        log.info("---====定时任务执行了:向first发送10条数据====---");
        for (int i = 1; i <=10 ; i++) {
            kafkaTemplate.send(TOPIC,i+"");
            log.info("---==="+i+"===---");
        }
    }
}

四、测试

创建first主题 、 三个分区 、 三个副本
first主题中发送10条消息,会到first 的三个分区中
在这里插入图片描述
可以看到,我们发送了10条消息到 first 主题的三个分区,
然后第一个消费者消费的 0和1 分区的消息,第二个分区 消费的是 2 分区的消息。
通过日志显示,消息并没有被重复消费

  • 4
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
### 回答1: 以下是使用Java编写Kafka消费者监听Topic的示例代码: ```java import java.util.Collections; import java.util.Properties; 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; public class KafkaConsumerExample { public static void main(String[] args) { Properties props = new Properties(); props.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); props.setProperty(ConsumerConfig.GROUP_ID_CONFIG, "test-group"); props.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); props.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props); consumer.subscribe(Collections.singletonList("test-topic")); while (true) { ConsumerRecords<String, String> records = consumer.poll(1000); for (ConsumerRecord<String, String> record : records) { System.out.println("Received message: " + record.value()); } } } } ``` 在上面的代码中,我们使用了KafkaConsumer类来创建一个Kafka消费者,并订阅了一个名为"test-topic"的Topic。然后,我们使用一个无限循环来轮询Kafka集群,以便在有新消息时能够及时处理。在每次轮询时,我们使用poll方法从Kafka集群中获取消息,并对每个消息进行处理。在这个示例中,我们只是简单地将消息内容打印到控制台。 ### 回答2: Kafka 是一种分布式流处理平台,它可以用于构建高可靠性、可扩展性和可容错性的实时数据流处理系统。使用 Java 编写 Kafka 监听消费 Topic 的代码如下: 首先,我们需要导入相关的 Kafka 相关包: ```java import java.util.Properties; 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; ``` 然后,我们可以创建 Kafka 消费者并设置相关属性: ```java Properties props = new Properties(); props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); // 设置 Kafka 服务器地址 props.put(ConsumerConfig.GROUP_ID_CONFIG, "my-group"); // 设置消费者组 ID props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); // 设置键反序列化器 props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); // 设置值反序列化器 KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(props); ``` 接下来,我们可以订阅要监听Topic: ```java consumer.subscribe(Arrays.asList("my-topic")); // 订阅主题,可以是单个主题或者多个主题 ``` 最后,我们可以循环监听消费消息: ```java while (true) { ConsumerRecords<String, String> records = consumer.poll(100); // 从 Kafka 中获取消息 for (ConsumerRecord<String, String> record : records) { System.out.printf("Topic: %s, Partition: %d, Offset: %d, Key: %s, Value: %s\n", record.topic(), record.partition(), record.offset(), record.key(), record.value()); // 在这里进行自定义的消息处理逻辑 } } ``` 以上就是使用 Java 编写 Kafka 监听消费 Topic 的基本代码。根据实际需求,你可以进一步处理消费的消息,例如将其保存到数据库、进行计算等等。同时,请确保你已经正确配置了 Kafka 的相关参数,包括 Kafka 服务器地址、消费者组 ID 等。 ### 回答3: Kafka是一个分布式的消息队列系统,允许多个消费者同时监听同一个主题topic)。以下是使用Java编写的Kafka监听topic消费的常见写法: 首先,需要引入Kafka的相关依赖: ``` <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka-clients</artifactId> <version>2.8.0</version> </dependency> ``` 接下来,创建一个Kafka消费者对象,并设置相关属性: ``` Properties props = new Properties(); props.put("bootstrap.servers", "localhost:9092"); // Kafka集群的地址 props.put("group.id", "my-consumer-group"); // 消费者组ID props.put("enable.auto.commit", "true"); // 自动提交消费位移 props.put("auto.commit.interval.ms", "1000"); // 消费位移提交间隔时间 props.put("auto.offset.reset", "earliest"); // 从最早的偏移量开始消费 props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); // key的反序列化器 props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); // value的反序列化器 KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props); ``` 然后,订阅要监听主题topic): ``` consumer.subscribe(Arrays.asList("my-topic")); // 订阅单个主题 // 或者 consumer.subscribe(Pattern.compile("my-topic.*")); // 订阅多个主题(使用正则表达式匹配) ``` 最后,开始消费消息: ``` try { while (true) { ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100)); // 每100毫秒拉取一次消息 for (ConsumerRecord<String, String> record : records) { String key = record.key(); String value = record.value(); long offset = record.offset(); int partition = record.partition(); System.out.println("Received message: key = " + key + ", value = " + value + ", offset = " + offset + ", partition = " + partition); // 处理消息的逻辑代码 } } } finally { consumer.close(); // 关闭消费者 } ``` 以上就是使用Java编写的Kafka监听topic消费的基本写法。其中,我们通过创建一个Kafka消费者对象,设置相关属性,订阅要监听主题,然后在一个无限循环中通过`poll`方法拉取消息进行消费。最后,记得在消费完成后关闭消费者

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Liu_Shihao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值