ps : kafka幂等是针对producer来说的
注意:幂等设计只能保证单个 Producer 对于同一个Partition的Exactly Once语义
1、消息语义
- At most once : 消息可能会丢失,但不会重复
- At least once : 消息不会丢失,但可能重复
- Exactly once : 正好一次。消息不会丢失也不会重复
2、为什么需要幂等?
- 在0.11.0.0之前,如果producer未能收到已提交消息的response,除了重新发送消息外别无选择,但提供了至少一次的语义保证。即原始请求已经成功,但因为某些原因(网络抖动、超时等问题),导致producer没有收到broker返回的数据ack,则producer会继续重试发送消息,从而导致消息重复发送。
- 从0.11.0.0开始,kafka producer支持幂等选项,该选项保证重新发送不会导致日志中出现重复条目
- 从0.11.0.0开始,kafka支持类似于将消息发送到多个分区的事务能力。即所有消息要么全部成功写入,要么都不成功。
3、幂等实现原理
- 引入了ProducerId(即PID)和Sequence Number
- ProducerID:初始化过程中,Broker会为每个生产者分配一个唯一的PID,该PID对用户完全透明的
- Sequence Number:每个对应PID的Producer发送数据时每条消息都对应一个从0 开始单调递增的序号
- broker端也会为每个<pid, topic, partitionId>维护一个序号,并且每次提交一条消息都会将序号递增。对于接收的消息,如果其序号比broker维护的序号(最后一次提交的消息编号)大1,则broker会接受它,否则将其丢弃:
- 如果消息序号比 Broker 维护的序号大于等于2,说明中间有数据尚未写入,也即乱序,此时 Broker 拒绝该消息,Producer 抛出OutofSequenceNumber
- 如果消息序号小于等于 Broker 维护的序号,说明该消息已被保存,即为重复消息,Broker 直接丢弃该消息,Producer 抛出DuplicateSequenceException
4、代码
props.put("enable.idempotence",true);