kafka isr副本管理机制与exactly once

一句话概述:
isr机制通过为维护一个与leader副本保持“同步状态”的集合,保证数据的一致性,提升了同步性能;ack机制与幂等性保证了数据的exactly once。

引入isr的原因

kafka并未采取Zab和Paxos协议的多数投票机制来来保证主备数据的一致性,而是提出了isr(in-sync- replicas)机制保证数据的一致性。

  • 多数投票机制,如果副本数是2f+1,那么最多允许f个副本发生故障;
  • isr机制,如果副本数是f+1,那么最多允许f个副本发生故障;
    相同容错指标下,位符的副本数量越多,则副本同步的效率也就越低。

几个核心概念:

  • LEO :每个副本都有的一个参数,表示当前副本的最后一个offset(Log End Offset)。
  • HW :同一个分区下所有副本共享的一个参数,表示所有副本的LEO的最小值,消费者只能消费这个offset之前的值
  • AR :所有部分的集合
  • ISR :保持与leader副本“同步”的集合,是AR的子集;该集合是动态变化的,落后过多的副本会被踢出ISR,追上来的副本会被加入到ISR集合中。

故障处理机制

  • 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同步数据。
    注意:这只能保证副本之间的数据一致性,并不能保证数据不丢失或者不重复。

如何实现exactly once

消息传递过程中的通用概念:

  • 最多一次(at most once): 消息可能丢失也可能被处理,但最多只会被处理一次。可能丢失 不会重复
  • 至少一次(at least once): 消息不会丢失,但可能被处理多次。可能重复 不会丢失
  • 精确传递一次(exactly once): 消息被处理且只会被处理一次。不丢失 不重复 就一次

ack机制:

kafka中有个参数 ack
0: producer完全不管broker的处理结果 回调也就没有用了 并不能保证消息成功发送 但是这种吞吐量最高
​-1或者all: leader broker会等消息写入 并且ISR都写入后 才会响应,这种只要ISR有副本存活就肯定不会丢失,但吞吐量最低。
​ 1: 默认的值 leader broker自己写入后就响应,不会等待ISR其他的副本写入,只要leader broker存活就不会丢失,即保证了不丢失,也保证了吞吐量。
所以设置为0时,实现了at most once,而且从这边看只要保证集群稳定的情况下,不设置为0,消息不会丢失。
但是还有一种情况就是消息成功写入,而这个时候由于网络问题producer没有收到写入成功的响应,producer就会开启重试的操作,直到网络恢复,消息就发送了多次。这就是at least once了。
kafka producer 的参数acks 的默认值为1,所以默认的producer级别是at least once。并不能exactly once。

幂等性:

kafka 0.11.0.0版本引入了idempotent producer机制,在这个机制中同一消息可能被producer发送多次,但是在broker端只会写入一次,他为每一条消息编号去重,而且对kafka开销影响不大。
但是幂等性只能保证单个分区的exactly once。
而多分区的情况,我们需要保证原子性的写入多个分区,即写入到多个分区的消息要么全部成功,要么全部回滚。

这样producer端实现了exactly once,那么consumer端呢?
consumer端由于可能无法消费事务中所有消息,并且消息可能被删除,所以事务并不能解决consumer端exactly once的问题,我们可能还是需要自己处理这方面的逻辑。比如自己管理offset的提交,不要自动提交,也是可以实现exactly once的。

总结:

kafka的多副本以及isr机制保证了数据的一致性,ack机制与幂等性保证了数据的精准一次。

posted @ 2021-11-28 10:48  桂花载酒少年游O  阅读(148)  评论(0编辑  收藏  举报