offset提交: Consumer消费数据后需要向kafka汇报消费的数据在partition offset位置

offset提交方式:自动提交、手动提交

1.自动提交

kafka一poll就自动提交offset

默认情况或者将props.put("enable.auto.commit", "true") --自动提交

自动提交流程:

consumer提交上次poll消息的偏移量——>consumer从kafka拉取新的消息

                          通过设置props.put("auto.commit.interval.ms", "2000")来决定自动提交间隔

 

自动提交优缺点:

优点:速度快

缺点:容易造成数据丢失。原因:消息poll下来后(还没有消费)直接提交offset,速度很快,可能出现消费失败。

自动提交示例代码:

Properties props = new Properties();
     props.put("bootstrap.servers", "localhost:9092");
     props.put("group.id", "test");
     props.put("enable.auto.commit", "true");
     props.put("auto.commit.interval.ms", "2000");
     props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
     props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
     KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
     consumer.subscribe(Arrays.asList("foo", "bar"));
     while (true) {
         ConsumerRecords<String, String> records = consumer.poll(100); //kafka一poll就提交offset了
         for (ConsumerRecord<String, String> record : records)
             System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value());

 

2.手动提交 commitAsync()

手动提交一般放到代码最后,这样上边程序都执行完后执行offset手动提交可以避免数据丢失问题 

properties.put("enable.auto.commit", "false"); --offset手动提交

手动提交可以细分为同步提交(commitSync)交和异步提交(commitAsync),同步/异步提交都会将本次poll的一批数据最高的偏移量提交。不同点

同步提交:提交时阻塞当前线程,一直等到提交成功,并且会自动失败重试

异步提交:提交完成后不需要等待broker返回ack直接往下走

手动提交必要性:

很多时候并不是说拉取到消息就算消费完成,而是需要将消息写入数据库、写入本地缓存,或者是更加复杂的业务处理。在这些场景下,所有的业务处理完成才能认为消息被成功消费,手动的提交方式可以让开发人员根据程序的逻辑在合适的地方进行位移提交

 

指定时间、分区 offset开始消费

指定时间
List<PartitionInfo> partitions=consumer.partitionsFor("topicName");
long fetchDataTime=new Date().getTime()-60*1000*100;
Map<TopicPartition,Long> timeToSearch=new HashMap<>();
List<TopicPartition> topicPartitions=new ArrayList<>();
for(PartitionInfo partitionInfo:partitions){
topicPartitions.add(new TopicPartition("TopicName",partitionInfo.partition()));
timeToSearch.put(new TopicPartition("TopicName",partitionInfo.partition()),fetchDataTime);
}
consumer.assign(Arrays.asList(new TopicPartition("TopicName",0));
consumer.offsetsForTimes(timeToSearch);

指定offset
int offset=10;
consumer.assign(Arrays.asList(new TopicPartition("TopicName",0))); //指定topic和partition=0
consumer.seekToBeginning(Arrays.asList(new TopicPartition("TopicName",0)));
consumer.seek(new TopicPartition("TopicName",0),offset);

参考:

指定时间消费

https://blog.csdn.net/lixinkuan328/article/details/120730555?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0-120730555-blog-120139470.pc_relevant_3mothn_strategy_and_data_recovery&spm=1001.2101.3001.4242.1&utm_relevant_index=3

指定offset消费

https://blog.csdn.net/weixin_57128596/article/details/127355594

posted on 2022-01-14 13:44  colorfulworld  阅读(1235)  评论(0编辑  收藏  举报