Kafka副本同步机制,HW和Leader Epoch

        最近在学习kafka的副本同步,感觉理解上比较绕,在看了官网介绍和一些博客后,总感觉必须要综合起来看才能理解,因此在此做一个总结。

1 基本概念

  • Kafka的Topic分为多个Partition,每个Partition又分为多个replica。这些replica中有1个leader和多个follower。leader负责处理消息的读写,follower负责和leader进行数据同步。
  • LEO:Log End Offset,日志末端位移,记录的是日志中最后一条消息的offset + 1。例如副本中最大记录的offset是6,那么LEO是7。

2 利用HW进行同步

2.1 基本概念

  • HW:High Watermark,高水位。HW限制了消费者可以读取的消息范围,消费者只能读取HW之前的数据,无法读取到HW以及之后的消息。
  • HW的作用:
    • 定义消费者可以读取的消息范围。

    • 副本同步,截取log文件。

2.2 副本同步步骤

  1. Follower向Leader请求同步数据;
  2. 下一轮RPC中,Follower向Leader确认确认收到了消息,Leader会记录所有Follower的LEO值,并选取最小的作为自己HW(增长水位)
  3. Leader在更新了自己的HW后,会比较HW和各个Follower的LEO值,选取较小的发给对应的Follower,作为该Follower的HW

        这样做的意义在于:

        第二步是Leader检查所有Follower的同步状况(由LEO表示),然后确保消费者能消费的部分(用HW表示)已经被所有Follower同步好了;

        第三步在于告知Follower目前的HW,也就是告知Follower哪一部分已经在所有Follower中都同步好了,因为Follower之间互不感知,所以这件事要Leader做。

        可能看到现在,还是看不出HW的具体作用,其实HW可以处理一些异常情况,接下来也会将。此外我们可以发现,在上述的过程中,Follower的HW总是滞后于Leader的。

2.3 异常情况下HW的作用

  • follower宕机:follower会被踢出ISR,待该follower恢复后,follower会读取磁盘上的HW,并把log文件高于HW的部分截掉,从HW开始重新向leader同步。等该follower的LEO大于等于该partition的HW后,即follower追上leader后,才能重新加入ISR。

  • leader宕机:从ISR中选出一个新的leader,为了保证多个副本的一致性,其余的follower会把各自的log文件中高于HW的部分截掉,然后向新的leader同步

2.4 仍然存在的问题

场景1:数据丢失

        假设replica A是follower,replica B是leader;A先从B获取消息m2,但HW还没来得及更新。此时A重启,根据HW把m2截掉了。然后A需要向B进行同步,但是B此时宕机了,于是A成了leader。leader中没有m2,无论B是否重启,m2都永远丢失了。如果B重启,那么会根据leader的HW裁掉m2。

        为了防止数据丢失,其实可以有两种方案。第一种是leader不要先更新HW,等待follower都更新好了再更新自己的,但是这样会造成网络延迟。第二种是follower恢复后,不要先根据自己的HW裁剪log,而是等待leader返回正确的HW后再裁剪,但是这种方法没法解决下面的数据不一致问题。

场景2:数据不一致

  • A和B同时宕机,比如断电了。此时B的消息比A少了一个m2。B先重启了,成为leader,然后生产者发消息给B,由于B没有follower,HW自然就加1了。此时A重启了,A的HW和 leader B相同,因此A不会裁掉m2,也无法感知这个位置上自己和leader的不同,导致了数据不一致。

3 利用Leader Epoch进行同步

3.1 基本概念

  • Leader Epoch:是一个键值对<Epoch, Offset>。Epoch表示Leader的版本号,每次变更Leader后都会+1,Offset表示当前版本的Leader从哪个Offset开始写入消息。例如<0, 0>和<1, 100>表示第一个leader从offset=0的位置开始写,第二个leader从offset=100的位置开始写。
  • Leader Epoch Request:follower宕机后,会向leader发送一个leader epoch request请求同步。如果follower记录的epoch落后于leader(宕机期间leader发生了变化),那么会返回follwer epoch + 1的offset;如果follower记录的epoch不落后于leader,那么leader会返回leader当前的LEO。

  • broker会在内存中缓存各个partition的replica的leader epoch数据,并且定期把这些信息持久化到一个checkpoint文件中。
  • 作用:代替HW,用于截取log。

3.2 场景1:解决数据丢失问题

        和之前的场景1一样。当A重启后,此时不再根据自己的HW去裁log,而是先发送一个Leader Epoch Request给leader,向 leader B 请求同步,此时两者的leader epoch相同,处于同一个epoch,那么A会拿到B的LEO作为offset去裁剪log,m2就保存下来了。

3.3 场景2:解决数据不一致问题

        和之前的场景2一样,A和B都断电了,消息较少的B先重启,然后成为leader,此时生产者写入消息m3,在B中保存的leader epoch是<0, 0>和<1, 1>。此时A重启,A不会再通过HW来裁剪log,而是会发送Leader Epoch Request给B,由于A记录的Leader Epoch落后于B记录的,A中保存的是<0, 0>,那么B就返回epoch 0的下一个epoch,即epoch 1的offset,也就是1。A拿到offset后,把这个offset以及之后的log截掉,此时不一致的m2就去除了,之后这个位置会同步为m3。

4 总结

        如果采用HW做log文件截断,可能会因为Follower和Leader之间的HW更新延迟,而导致数据丢失或者数据不一致。

        因此kafka引入了Leader Epoch作为裁log文件的方法。leader epoch实际上时当前leader告知follower,从哪次leader变动的offset开始,follower不知情,然后follower需要根据这个offset,把自己不知情部分的log文件重新同步。

5 参考资料

KIP-101 - Alter Replication Protocol to use Leader Epoch rather than High Watermark for Truncation - Apache Kafka - Apache Software Foundation

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值