上一节最后总结了分区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也会发生变化。