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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通