kafka数据丢失和重复消费解决方案

在使用消息中间间的过程中,经常面对的问题就是消息丢失和重复消费,本文主要记录kafka消息丢失和重复消费的解决思想,不做具体实现。

生产者

消息丢失

丢失场景

  • 配置文件里面,ack设置为0,也就是生产者发送之后,producer将消息存到缓存buffer之后,就会返回成功,此时分区副本(leader和follower)并不能保证落盘成功,

此时如果出现网络抖动等问题就会导致数据丢失。

  • ack设置为1,也就是生产者发送之后,只要leader接收到了,就会返回成功,follower没来及同步的时候leader挂掉,也会导致消息丢失。

解决方案

设置ack=all/-1,保证leader和follower分区都收到之后,再返回给生产者成功。如果其中有一个步骤异常,都会触发kafka的重试机制。

重复消费

重复场景

生产发送的消息没有收到正确的broke响应,导致producer重试。producer发出一条消息,broke落盘以后因为网络等种种原因,发送端得到一个发送失败的响应或者网络中断,然后producer收到一个可恢复的Exception重试消息导致消息重复。

解决办法

启动kafka的幂等性

enable.idempotence=true 同时要求 ack=all 且 retries>1。

幂等原理:

每个生产者producer都有一个唯一id,producer每发送一条数据,都会带上一个sequence,当消息落盘,sequence就会递增1。那么只需要判断当前消息的sequence是否大于当前最大sequence,大于就代表此条数据没有落盘过,可以正常消费。不大于就代表落盘过,这个时候重发的消息会被服务端拒掉从而避免消息重复。

broker

丢失场景

  • ack=1,follower没来及同步的时候leader挂掉,当follower被选举为新的leader时,这部分没同步的数据就丢失了。
  • 分区副本数小于2个,导致没有足够数量的副本参与新leader选举,无法保证数据的高可用,当原leader挂了之后,没有follower被选举为leader。

解决办法:

  • ack=-1,保证leader和follower分区的数据可以落盘。
  • 保证分区副本数大于2,保证数据的高可用性
  • 设置重试次数等。

消费者

消息丢失

丢失场景

设置的自动提交offset,当消费者已经消费到了消息,也记录了新的偏移量offset,但是后面的业务失败了或者没来得及处理就挂了。这时候因为offset已经更新了,这条消息也再消费不到了。

解决办法

设置为手动提交成功,当业务代码都执行完成之后,再进行手动提交,确保消息被真正处理到。

消息重复

重复场景

数据消费完没有及时提交offset到broke。消息消费端在消费过程中挂掉没有及时提交offset到broke,另一个消费端启动拿之前记录的offset开始消费,由于offset的滞后性可能会导致新启动的客户端有少量重复消费。

解决办法

  • 设置为手动提交成功
  • 在下游程序里面做幂等

幂等的两种方法:

  1. 将唯一键存入第三方介质,要操作数据的时候先判断第三方介质(数据库或者缓存)有没有这个唯一键。
  2. 将版本号(offset)存入到数据里面,然后再要操作数据的时候用这个版本号做乐观锁,当版本号大于原先的才能操作。

参考链接

https://blog.csdn.net/qq_39188150/article/details/111415881

Search by:GoogleBingBaidu