【Java面试】Kafka 怎么避免重复消费

  • 2022 年 6 月 24 日
  • 笔记

Hi,大家好,我是Mic

一个工作5年的粉丝找到我。

他说: “Mic老师,你要是能回答出这个问题,我就佩服你”

我当场就懵了,现在打赌都这么随意了吗?

我问他问题是什么,他说“Kafka如何避免重复消费的问题!”

下面看看普通人和高手的回答!

普通人:

Kafka怎么避免重复消费就是我们可以通过 我们可以在那个消息消费的这一端就是我们可以用类似于分布式锁的这样一个设计吧。

我消费一个消息的时候我可以直接用比如说redis里面的setNx这样一个指令,然后去把那个消息保存到redis里面然后后面再如果重复发送的话那我就直接只要去判断这个Redis里面有没有存在就好了。

高手:

好的,关于这问题,我从几个方面来回答。

首先Kafka Broker上存储的消息,都有一个Offset标记。

然后kafka的消费者是通过offSet标记来维护当前已经消费的数据,

每消费一批数据,Kafka Broker就会更新OffSet的值,避免重复消费。

image-20220513132307557

默认情况下,消息消费完以后,会自动提交Offset的值,避免重复消费。

Kafka消费端的自动提交逻辑有一个默认的5秒间隔,也就是说在5秒之后的下一次向Broker拉取消息的时候提交。

所以在Consumer消费的过程中,应用程序被强制kill掉或者宕机,可能会导致Offset没提交,从而产生重复提交的问题。

除此之外,还有另外一种情况也会出现重复消费。

在Kafka里面有一个Partition Balance机制,就是把多个Partition均衡的分配给多个消费者。

Consumer端会从分配的Partition里面去消费消息,如果Consumer在默认的5分钟内没办法处理完这一批消息。

就会触发Kafka的Rebalance机制,从而导致Offset自动提交失败。

而在重新Rebalance之后,Consumer还是会从之前没提交的Offset位置开始消费,也会导致消息重复消费的问题。

image-20220513140121369

基于这样的背景下,我认为解决重复消费消息问题的方法有几个。

  1. 提高消费端的处理性能避免触发Balance,比如可以用异步的方式来处理消息,缩短单个消息消费的市场。或者还可以调整消息处理的超时时间。还可以减少一次性从Broker上拉取数据的条数。
  2. 可以针对消息生成md5然后保存到mysql或者redis里面,在处理消息之前先去mysql或者redis里面判断是否已经消费过。这个方案其实就是利用幂等性的思想。

以上就是我对这个问题的理解。

总结

重复消费这个问题很重要,如果没有考虑到就会出现线上的数据问题。

所以在面试的时候,这些问题也能够考察求职者的技术能力以及实践能力。

另外,关于幂等性的问题,我在前面的视频里面有讲,大家可以自己找一找。

喜欢我的作品的小伙伴记得点赞和收藏加关注。

file

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Mic带你学架构
如果本篇文章对您有帮助,还请帮忙点个关注和赞,您的坚持是我不断创作的动力。欢迎关注“跟着Mic学架构”公众号公众号获取更多技术干货!