Kafka在什么情况下会出现消息丢失及解决方案?
ACK应答机制可以在生产者向队列写入数据的时候可以设置参数来确定是否确认kafka接收到数据,这个参数可设置的值为0、1、2、…all。
0代表producer往集群发送数据不需要等到集群的返回,不确保消息发送成功。安全性最低但是效率最高。
1代表producer往集群发送数据只要leader应答就可以发送下一条,只确保leader发送成功。
2代表producer往集群发送数据需要至少一个follower都完成从leader的同步才
会发送下一条,可以保证leader宕机了至少还有一个follower有数据。
all或-1代表producer往集群发送数据需要ISR下所有的follower都完成从leader的同步才会发送下一条,确保leader发送成功和ISR下所有的所有的副本都完成备份。安全性最高,但是效率最低。
ISR:可靠的follower,跟leader节点保持一致的follower才会维护到ISR
1)消息发送
1、ack=0,不重试
producer发送消息完,不管结果了,如果发送失败也就丢失了。
2、ack=1,leader crash
producer发送消息完,只等待lead写入成功就返回了,leadercrash了,这时follower没来及同步,消息丢失。
3、unclean.leader.election.enable 配置true
允许选举ISR以外的副本作为leader,会导致数据丢失,默认为false。producer发送异步消息完,只等待lead写入成功就返回了,leadercrash了,这时ISR中没有follower,leader从OSR中选举,因为OSR中本来落后于Leader造成消息丢失。
解决方案:
1、配置:ack=all / -1,tries > 1,unclean.leader.election.enable : false
producer发送消息完,等待follower同步完再返回,如果异常则重试,至少大于1。不允许选举ISR以外的副本作为leader。副本的数量可能影响吞吐量。
2、配置:min.insync.replicas > 1
同步时 *** 作成功的最小副本数量,副本指定必须确认写 *** 作成功的最小副本数量。如果不能满足这个最小值,则生产者将引发一个异常(要么是NotEnoughReplicas,要么是NotEnoughReplicasAfterAppend)。
min.insync.replicas > 1时,ISR里的follower数量必须大于1。
ack必须设置为all或-1,min.insync.replicas参数才生效。
min.insync.replicas和ack搭配可以有更大的持久性保证。确保如果大多数副本没有收到写 *** 作,则生产者将引发异常。
3、失败的offset单独记录
producer发送消息,会自动重试,遇到不可恢复异常会抛出,这时可以捕获异常记录到数据库或缓存,进行单独处理。
2)消费
先commit再处理消息。如果在处理消息的时候异常了,但是offset已经提交了,这条消息对于该消费者来说就是丢失了,再也不会消费到了。
解决方案:先处理消息再commit,但须保证处理消息接口的幂等性,防止重复消费消息。
3)broker的刷盘
减小刷盘间隔(从broke缓存刷到文件系统中的pagecache中),合理设置下面的参数
当达到下面的消息数量时,会将数据flush到日志文件中。默认10000
#log.flush.interval.messages=10000
#当达到下面的时间(ms)时,执行一次强制的flush *** 作。interval.ms和interval.messages无论哪个达到,都会flush。默认3000ms
#log.flush.interval.ms=1000
在Linux系统中,当我们把数据写入文件系统之后,其实数据在 *** 作系统的pagecache里面,并没有刷到磁盘上。如果 *** 作系统挂了,数据就丢失了。一方面,应用程序可以调用fsync这个系统调用来强制刷盘,另一方面, *** 作系统有后台线程,定时刷盘。频繁调用fsync会影响性能,需要在性能和可靠性之间进行权衡。实际上,官方不建议通过上述的三个参数来强制写盘,认为数据的可靠性通过replica来保证,而强制flush数据到磁盘会对整体性能产生影响。
Kafka的持久性并非要求同步数据到磁盘,因为问题节点都是从副本中恢复数据。这样刷盘依赖 *** 作系统及Kafka的后台刷盘机制。这样的好处是:无需调优、高吞吐量、低延时和可全量恢复
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)