Kafka数据可靠性保证
笔记来源于尚硅谷视频课程
一、ACK应答机制
对于某些不太重要的数据,对数据的可靠性要求不是很高,能够容忍数据的少量丢失,所以没必要等 ISR 中的 follower 全部接收成功。
怎么确定producer 的消息发送到了Kafka?
Kafka收到消息后会向producer 发送一个ack(acknowledgement 确认收到),producer 收到之后进行下一轮的发送,否则重新发送数据。
acks的参数配置:
此配置是 Producer 在确认一个请求发送完成之前需要收到的反馈信息的数量。 这个参数是为了保证发送请求的可靠性。以下配置方式是允许的:
-
acks=0
如果设置为0,则 producer 不会等待服务器的反馈。该消息会被立刻添加到 socket buffer 中并认为已经发送完成。在这种情况下,服务器是否收到请求是没法保证的,并且参数retries
也不会生效(因为客户端无法获得失败信息)。每个记录返回的 offset 总是被设置为-1。 -
acks=1
如果设置为1,leader节点会将记录写入本地日志,并且在所有 follower 节点反馈之前就先确认成功。在这种情况下,如果 leader 节点在接收记录之后,并且在 follower 节点复制数据完成之前产生错误,则这条记录会丢失。 -
acks=all
如果设置为all,这就意味着 leader 节点会等待所有同步中的副本确认之后再确认这条记录是否发送完成。只要至少有一个同步副本存在,记录就不会丢失。这种方式是对请求传递的最有效保证。acks=-1与acks=all是等效的。
二、副本同步策略
follower主动去请求leader进行同步的
当acks=all 时,就需要副本同步完成再给producer发送确认。
副本同步时是全部副本都同步完成吗?
不是,Leader 维护了一个动态的 in-sync replica set (ISR),意为和 leader 保持同步的 follower 集合。当 ISR 中的 follower 同步完成,表示可以返回ack确认收到消息。
怎样的副本能进入ISR集合呢?
0.9之前的版本进入ISR集合的因素有两个:在阈值时间内、消息条数。
在时间阈值内相应的follower同步完成的,将该follower加入ISR集合。如果 follower长时间 未 向 leader 同 步 数 据 , 则 该 follower 将 被 踢 出 ISR , 该 时 间 阈 值 由replica.lag.time.max.ms 参数设定。
同步时leader挂了的情况怎么处理?
Leader 发生故障之后,就会从 ISR 中选举新的 leader。
三、故障处理

LEO:指的是每个副本最大的offset;
HW:指的是消费者能见到的最大的offset,ISR 队列中最小的 LEO。
follower故障
follower 发生故障后会被临时踢出 ISR,待该 follower 恢复后,follower 会读取本地磁盘记录的上次的 HW,并将 log 文件高于 HW 的部分截取掉,从 HW 开始向 leader 进行同步。等该 follower 的 LEO 大于等于该 Partition 的 HW,即 follower 追上 leader 之后,就可以重新加入 ISR 了。
leader故障
leader 发生故障之后,会从 ISR 中选出一个新的 leader,之后,为保证多个副本之间的数据一致性,其余的 follower 会先将各自的 log 文件高于 HW 的部分截掉,然后从新的 leader同步数据。
注意:HW只能保证副本之间的数据一致性,并不能保证数据不丢失或者不重复。
什么情况下数据会丢失?
当ack!=all情况下:all=0时,未收到确认消息,producer就继续执行了,无法保证不丢数据;当ack=1时,leader收到数据返回ack,follower未同步完成,这时leader挂了,然后进行选举leader进行同步,这时就会丢失数据。
什么情况下会造成数据重复?
当ack=all情况下:当leader还未给producer发送ack确认消息,这时挂掉,这时follower(ISR)只同步了一部分数据,然后进行选举leader进行同步,这时producer未收到确认就会重发消息,这时就造成了数据重复。
四、Exactly One 语义
将服务器的 ACK 级别设置为-1,可以保证 Producer 到 Server 之间不会丢失数据,即 AtLeast Once 语义。相对的,将服务器 ACK 级别设置为 0,可以保证生产者每条消息只会被发送一次,即 At Most Once 语义。
At Least Once 可以保证数据不丢失,但是不能保证数据不重复;相对的,At Least Once可以保证数据不重复,但是不能保证数据不丢失。但是,对于一些非常重要的信息,比如说交易数据,下游数据消费者要求数据既不重复也不丢失,即 Exactly Once 语义。在 0.11 版本以前的 Kafka,对此是无能为力的,只能保证数据不丢失,再在下游消费者对数据做全局去重。对于多个下游应用的情况,每个都需要单独做全局去重,这就对性能造成了很大影响。
0.11 版本的 Kafka,引入了一项重大特性:幂等性。所谓的幂等性就是指 Producer 不论向 Server 发送多少次重复数据,Server 端都只会持久化一条。幂等性结合 At Least Once 语义,就构成了 Kafka 的 Exactly Once 语义。即:
At Least Once + 幂等性 = Exactly Once
要启用幂等性,只需要将 Producer 的参数中 enable.idompotence 设置为 true 即可。Kafka的幂等性实现其实就是将原来下游需要做的去重放在了数据上游。开启幂等性的 Producer 在初始化的时候会被分配一个 PID,发往同一 Partition 的消息会附带 Sequence Number。而Broker 端会对<PID, Partition, SeqNumber>做缓存,当具有相同主键的消息提交时,Broker 只会持久化一条。
但是 PID 重启就会变化,同时不同的 Partition 也具有不同主键,所以幂等性无法保证跨
分区跨会话的 Exactly Once。
五、保证数据不重复并且不丢失的方式
ack设置为all(-1) ,启用幂等性即可。
网友评论