0%

生产者如何保证不丢数据

生产者如何保证不丢数据

生产者是通过ack确认机制来进行保证数据可靠的,topic的每一个partition收到生产者发送的数据后,都需要向生产者发送ack,如果生产者收到ack,则会进行下一轮的发送,否则就会重发数据。

而kafka中一个partition分区包含有一个leader和多个follower副本,而leader是与生产者进行读写交互的,那么partition中的leader何时向生产者回复ack呢?leader下有一个isr(in-sync replica set),isr存储的是与leader保持同步的follower集合,只有当isr中的follower完成数据同步后,leader才会向生产者发送ack,如果follower长时间没有向leader同步数据,则该follower会被踢出isr,该时间由replica.lag.time.max.ms 参数设定,如果leader发生故障之后,会从isr中进行选举出新的leader

而kafka中ack确认机制有三种级别

acks确认机制,用于配置代理接收到消息后向生产者发送确认信号,以便生产者根据acks进行相应的处理,该机制通过属性request.required.acks设置,0、-1、1三种,默认1

  • acks=0时,生产者不需要等待代理返回确认消息,而连续发送消息。消息投递速度加快,broker接收了但是没有写入磁盘,但是无法保证消息的持久化,如果broker故障就可能丢失数据

  • acks=1时,生产者需要等待leader副本已成功将消息写入日志文件。降低了数据丢失的可能性,但还是存在,如果在leader成功存储数据后,follower没有来得及同步,此时leader挂掉了,而follower没有进行同步,从isr中选举出来新的leader也就没有这条数据,数据就会丢失

  • acks=-1时,leader副本和所有ISR列表中的副本都完成数据存储之后才会向生产者发送确认消息,这种策略保证只要leader副本和follower副本中至少有一个节点存活,数据就不会丢失,但是如果数据同步完成之后,leader没有返回ack之前leader发生故障,导致生产者数据重发,会因此而导致数据重复

对于数据重复的情况,可以采用幂等性,保证同一条数据只存储一次,要启用幂等性,只需要将 Producer 的参数中 enable.idompotence 设置为 true 即可。Kafka的幂等性实现其实就是将原来下游需要做的去重放在了数据上游。开启幂等性的 Producer 在初始化的时候会被分配一个 PID,发往同一 Partition 的消息会附带 Sequence Number。而Broker 端会对<PID, Partition, SeqNumber>做缓存,当具有相同主键的消息提交时,Broker 只会持久化一条。
但是 PID 重启就会变化,同时不同的 Partition 也具有不同主键,所以幂等性无法保证跨分区跨会话的重复。