为什么消费者会重复消费消息、漏消息?
我们先了解一下我们是怎么消费消息的,一个消费者启动时,offset会被初始化为0,这代表我们从0开始消费,每消费一条消息,offset会递增一次。如果一直正常消费(消费者不故障)是不会导致消息重复消费以及漏消息的。但是当以下两种情况发生时,会分别发生漏消息与重复消费消息的情况;
1.先提交offset,再消费消息
offset被提交到kafka broker,但是消息还没来得及被消费,消费者故障了需要重启,由于offset已经被提交了,所以这个情况会发生漏消费的问题。
2.先消费消息,再提交offset
先把消息消费完了,但offset还未被提交,消费者故障重启,消息已经被消费,但offset未提交,此时故障会产生消息重复消费的问题。
---------------------------------------------------------------------------------------------------------------------------------
Kafka的自动提交offset与手动提交offset
首要要给大家说明的是不论是手动提交或是自动提交皆会有出错的风险
一、自动提交offset
自动提交offset使用enable.auto.commit=truefalse来开启或关闭,自动offset是根据配置参数的时间来决定提交间隔的(auto.commit.interval.ms)来决定的,这意味着自动提交可能出现重复消费的情况(也就是消费了消息、消费者还没提交offset就故障了);
二、手动提交offset
相对于自动提交来说手动提交的优点是我们可以更好的把握提交时机,但手动提交也有失败的风险(Timeout、故障等),把自动关闭我们就需要手动提交offset。手动提交有两种方式
1.同步提交(commitSync)
同步提交在消费过后显示调用consumer.commitSync(),会阻塞线程并且失败会重新尝试提交。相比异步提交它的优点是可用性比异步提交强。
2.异步提交(commitAsync)
异步提交在消费过后显示调用consumer.commitAsync(),没有重新提交机制。它的优点是不会阻塞线程因此效率更高。
---------------------------------------------------------------------------------------------------------------------------------
如何避免消息重复消费、漏消费的情况?
在这一块来看应该是仁者见仁、智者见智啦!
1.如果消息有ID主键的话,那么我觉得可以先消费数据、再提交offset,这样首先保证了不会丢失数据(假设这个批次消费从100-110的数据,offset当前为100,消费到105条时消费者故障重启,此时offset还是100),在消费数据时我们可以添加checking如果消息已经存在db中或内存中、我们就不进行本次 *** 作。这样我们可以跃过已经重复消费的数据。这样可以浪费一点资源来保全我们的数据不重复消费也不漏消费。
2.根据事务的特性,一组 *** 作要么全部成功,要么全部失败,我们可以将(消费者消费数据,消费者提交offset)两个 *** 作都在一个事务中进行,进而保证两个 *** 作同时成功或失败、达到我们既不重复消费数据也不漏消费消息的目的
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)