说明:转载本人掘金文章
offset是相对Consumer来说的,offset是用来帮助记录某个主题某个分区的消费情况的。当你每提交一次offset,意味着向kafka汇报一次消费进度,对于提交offset所以又分为同步和异步提交
同步提交:
1.每次处理完一条消息,然后调用consumer.commitSync()提交offset
2.在调用consumer.commitSync()方法时候会堵塞住,严重影响消费者性能
3.每次提交都会向__consumer_offsets发送一条消息,增加__consumer_offsets提交频率,影响kafka性能
4.同步提交好处在于不会出现重复消费的情况,处理每条都及时被kafka记录下来
异步提交:
1.每次提交了(commitAysnc())一些offset之后,会提交最后一个offset最大的
2.在调用commitAysnc()不会阻塞消费者,一定程度提高了消费者处理消息性能
3.每隔一批消息,真正汇报一次offset到kafka,但是如果中间发生异常,提交offset失败将导致重复消息
同步提交:
//配置
spring.kafka.consumer.enable-auto-commit=false
spring.kafka.listener.ack-mode=manual_immediate //立刻提交
//每次调用ack.acknowledge()会提交,会提交一次offset
@KafkaHandler
@KafkaListener(topics = "quickstart-events",groupId = "test-consumer-group-4",concurrency = "1")
public void test11(ConsumerRecord record, Acknowledgment ack){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("接收消息:"+String.format(
"(消息体)%s--(分区)%s--(消费者实例)%s",record.value(),record.partition(),Thread.currentThread().getName()));
ack.acknowledge();
}
投入10条消息
消费前__consumer_offsets的48分区情况
消费后__consumer_offsets的48分区情况
说明:可以看到__consumer_offsets的48分区多了11(多的一条我们先不讨论)条消息
异步提交:
//配置
spring.kafka.consumer.enable-auto-commit=false
spring.kafka.listener.ack-mode=manual //不是马上提交,而是按照异步批次提交一次
//增加max.poll.records=4参数,意味者一批4条消息,10条消息应该提交三次offset
@KafkaHandler
@KafkaListener(topics = "quickstart-events",properties = {"max.poll.records=4"},groupId = "test-consumer-group-4",concurrency = "1")
public void test11(ConsumerRecord record, Acknowledgment ack){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("接收消息:"+String.format(
"(消息体)%s--(分区)%s--(消费者实例)%s",record.value(),record.partition(),Thread.currentThread().getName()));
ack.acknowledge();
}
投入10条消息
消费前__consumer_offsets的48分区情况
消费后__consumer_offsets的48分区情况
说明:可以看到__consumer_offsets的48分区多了4(多的一条我们先不讨论)条消息
可以看到异步提交不仅可以提高消费端性能,同时__consumer_offsets的压力也会降低,其实按照批次异步提交方案是最佳选择,只要我们做好消费端幂等性即可