简介
本文介绍什么时候消息会重复(场景)、保证消息不重复(精准一次)的方案。
Kafka的消息重复是消息异常中的一种。其他异常还有:消息丢失、顺序性、消息堆积等。本文只介绍消息重复这种消息异常。
Kafka消息在生产者、Broker、消费者 都可能导致重复。
生产者消息重复
场景1:生产者重试
描述
生产发送的消息没有收到正确的broke响应,导致producer重试。
详解:producer发出一条消息,broker落盘以后,因为网络等原因,发送端得到一个发送失败的响应或者网络中断,然后producer收到一个可恢复的Exception重试消息导致消息重复。
解决方案
启动kafka的幂等性
方案结论
enable.idempotence=true //此时会默认开启acks=all
acks=all
retries>1
详解
kafka 0.11.0.0版本之后,正式推出了idempotent producer,支持生产者的幂等。
每个生产者producer都有一个唯一id,producer每发送一条数据都会带上一个sequence,当消息落盘,sequence就会递增1。只需判断当前消息的sequence是否大于当前最大sequence,大于就代表此条数据没有落盘过,可以正常消费;不大于就代表落盘过,这个时候重发的消息会被服务端拒掉从而避免消息重复。
消费者消息重复
场景1:消费成功后,offset提交失败
描述
Kafka默认情况下是先消费消息,再提交offset。如果消费者在消费了消息之后,消费者挂了,还未提交offset,那么Broker后边会重新让消费者消费。
解决方案1:业务代码中处理
结论
手动判断幂
详解
幂等实际上就两种方法:
(1)、将唯一键存入第三方介质,要操作数据的时候先判断第三方介质(数据库或者缓存)有没有这个唯一键。
(2)、将版本号(offset)存入到数据里面,然后再要操作数据的时候用这个版本号做乐观锁,当版本号大于原先的才能操作。
解决方案2:Kafka Streams
使用kafka的流处理引擎:Kafka Streams(此法用的很少)
设置processing.guarantee=exactly_once,就可以轻松实现exactly once了。
请先
!