Kafka的消费者提交方式手动同步提交、和异步提交

1、Kafka的消费者提交方式

  1)、自动提交,这种方式让消费者来管理位移,应用本身不需要显式操作。当我们将enable.auto.commit设置为true,那么消费者会在poll方法调用后每隔五秒(由auto.commit.interval.ms指定)提交一次位移。和很多其他操作一样,自动提交也是由poll方法来驱动的,在调用poll方法的时候,消费者判断是否到达提交时间,如果是则提交上一次poll返回的最大位移。需要注意的是,这种方式可能会导致消息重复消费,假如,某个消费者poll消息后,应用正在处理消息,在3秒后kafka进行了重平衡,那么由于没有更新位移导致重平衡后这部分消息重复消费。

  2)、同步提交。

 1 package com.demo.kafka.consumer;
 2 
 3 import java.time.Duration;
 4 import java.util.Arrays;
 5 import java.util.Collections;
 6 import java.util.List;
 7 import java.util.Properties;
 8 import java.util.regex.Pattern;
 9 
10 import org.apache.kafka.clients.consumer.ConsumerConfig;
11 import org.apache.kafka.clients.consumer.ConsumerRecord;
12 import org.apache.kafka.clients.consumer.ConsumerRecords;
13 import org.apache.kafka.clients.consumer.KafkaConsumer;
14 import org.apache.kafka.clients.consumer.OffsetAndMetadata;
15 import org.apache.kafka.clients.producer.ProducerConfig;
16 import org.apache.kafka.common.TopicPartition;
17 import org.apache.kafka.common.serialization.StringDeserializer;
18 
19 public class KafkaConsumerSimple {
20 
21     // 设置服务器地址
22     private static final String bootstrapServer = "192.168.110.142:9092";
23 
24     // 设置主题
25     private static final String topic = "topic-demo";
26 
27     // 设置主题
28     private static final String topic2 = "topic-demo2";
29 
30     // 设置消费者组
31     private static final String groupId = "group.demo";
32 
33     public static void main(String[] args) {
34         Properties properties = new Properties();
35         // 设置反序列化key参数信息
36         properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
37         // 设置反序列化value参数信息
38         properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
39 
40         // 设置服务器列表信息,必填参数,该参数和生产者相同,,制定链接kafka集群所需的broker地址清单,可以设置一个或者多个
41         properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServer);
42 
43         // 设置消费者组信息,消费者隶属的消费组,默认为空,如果设置为空,则会抛出异常,这个参数要设置成具有一定业务含义的名称
44         properties.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);
45 
46         // 制定kafka消费者对应的客户端id,默认为空,如果不设置kafka消费者会自动生成一个非空字符串。
47         properties.put("client.id", "consumer.client.id.demo");
48 
49         // 设置每次从最早的offset开始消费
50         properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
51 
52         // 手动提交开启
53         properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
54 
55         // 将参数设置到消费者参数中
56         KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(properties);
57 
58         // 消息订阅
59         // consumer.subscribe(Collections.singletonList(topic));
60         // 可以订阅多个主题
61         // consumer.subscribe(Arrays.asList(topic, topic2));
62         // 可以使用正则表达式进行订阅
63         // consumer.subscribe(Pattern.compile("topic-demo*"));
64 
65         // 指定订阅的分区
66         TopicPartition topicPartition = new TopicPartition(topic, 0);
67         consumer.assign(Arrays.asList(topicPartition));
68 
69         // 初始化offset位移为-1
70         long lastConsumeOffset = -1;
71         while (true) {
72             // 每隔一秒监听一次,拉去指定主题分区的消息
73             ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(1000));
74             if (records.isEmpty()) {
75                 break;
76             }
77             // 获取到消息
78             List<ConsumerRecord<String, String>> partitionRecords = records.records(topicPartition);
79             // 获取到消息的offset位移信息,最后消费的位移
80             lastConsumeOffset = partitionRecords.get(partitionRecords.size() - 1).offset();
81             // System.out.println("the last offset is " + lastConsumeOffset);
82             // 同步提交消费位移
83             consumer.commitSync();
84         }
85         // 当前消费者最后一个消费的位置
86         System.out.println("consumed offset is " + lastConsumeOffset);
87         // 提交,下次消费从哪个位置开始
88         OffsetAndMetadata committed = consumer.committed(topicPartition);
89         System.out.println("committed offset is " + committed.offset());
90         // 下次消费从哪个位置开始
91         long position = consumer.position(topicPartition);
92         System.out.println("the offset of the next record is " + position);
93 
94     }
95 
96 }

  3)、异步提交方式。手动提交有一个缺点,就是当发起提交时调用应用会阻塞。当然我们可以减少手动提交的频率,但这个会增加消息重复的概率(和自动提交一样)。另外一个解决方法是,使用异步提交。但是异步提交也有一个缺点,那就是如果服务器返回提交失败,异步提交不会进行重试。相比较起来,同步提交会进行重试知道成功或者最后抛出异常给应用。异步提交没有实现重试是因为,如果同时存在多个异步提交,进行重试可能会导致位移覆盖。比如,我们发起一个异步提交commitA,此时提交位移是2000,随后又发起了一个异步提交commitB且位移为3000,commitA提交失败但commitB提交失败,此时commitA进行重试并成功的话,会将实际上已经提交的位移从3000回滚到2000,导致消息重复消费。

 1 package com.demo.kafka.consumer;
 2 
 3 import java.time.Duration;
 4 import java.util.Arrays;
 5 import java.util.Map;
 6 import java.util.Properties;
 7 import java.u
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值