天天看点

【kafka】生产者投递消息exactly once 精准一次性(幂等性解决消息重复投递)

上一节最后总结了分区HW高水位线的意义: 保证了副本数据之间的一致性 保证了消费者消费数据的一致性 不能保证数据投递不丢失或者不重复。

今天就来解决消息丢失或者重复问题

producer发送消息的时候可以设置ack等级:

at most once 最多一次 acks=0 只发送一次,丢数据,不会重复发送 at lestest once 最少一次 acks=-1或者all,不丢失数据,但可能重复数据。

如何实现消息投递exactly once 精准一次性?

目标:不丢失数据,不重复数据。

至少一次可以保证数据不丢失,再进行去重即可。

at lestest once+幂等性= exactly once

幂等性解释:

是指producer无论向broker发送了多少条重复的消息,broker只会持久化一条。

如何启用幂等性?

在producer中开启enable.idompotence=true,此时默认就开启了acks=-1|all

幂等性实现原理:

producer连接到broker的时候会分配一个PID (producer_id),producer发送消息到统一个分区partition的时候,消息会附带一个sequence number序列号,broker会以<PID,Patition,SeqNumber>作为主键key进行缓存,当具有相当的 主键key的消息进行提交的时候,Broker只会持久化一条。

kafka中幂等性存在的问题:

幂等性只解决了当前的会话且当前的分区的幂等性。跨分区、会话不能实现精准一次性投递写入。

当producer重启后,broker分配的PID(producer_id)会发生变化。切换分区后,Patition也发生了变化。最终导致<PID,Patition,SeqNumber>作为主键的key也会发生变化。