likes
comments
collection
share

技术大佬问我,kafka是如何做到数据的高可靠的(下)

作者站长头像
站长
· 阅读数 59

佩琪:  大佬,你昨天给讲了kafka数据高可靠 主从同步的概念和过程;但还留了个尾巴,kafka主从同步两阶段协议里存在的问题还没有讲了

技术大佬 : (幸亏上次到饭点,否则就尬死了,这个佩琪问题真多,没办法还需要继续装下去)

技术大佬 : 在主从同步时,如果只靠HW和LEO,在某些特殊的情况下,确实存在两种问题。一种是 数据会丢失;另外一种是数据可能会不一致

技术大佬问我,kafka是如何做到数据的高可靠的(下)

佩琪: 什么样的特殊条件下了?

技术大佬 : 准确说是在 min.insync.replicas=1 这种特殊设置下(级leader partition写入消息到本地,就代表了“消息已提交”)

佩琪: 那在这种情况下,依靠HW和LEO的主从同步,是如何导致数据丢失的呢?

技术大佬 : 咱们看图说话?(资料来自于 kafka KIP官方文档)

技术大佬问我,kafka是如何做到数据的高可靠的(下)

  1. (A) 在同步的第一阶段,从 (B)拉取m2消息写入到本地文件系统
  2. (A) 突然宕机了(还来不及发送第二次请求 获取leader HW)
  3. 此时副本(A)重新启动。它将其日志截断至高水位线 并向领导者 (B) 发出获取请求。
  4. (B) 然后失败,A 成为新的领导者。消息m2已经永久丢失(无论B是否回来)。

技术大佬 : 从上面的过程 可看到 这种数据的丢失,是由于kafka 在进行重启恢复时,由截断日志的机制和 min.insync.replicas=1的情况下,共同造成的。

佩琪: min.insync.replicas=1的情况下,数据可能会丢失,这我还能理解,毕竟min.insync.replicas=1 表示只要有一个副本把消息写入成功,就表示消息已提交了。比如leader partition 写入消息到文件系统成功,就表示已提交;但如果leader partition 所在的broker都宕机了,那么在为1的条件下,kafka是不能保证leader切换后, 这种情况消息不丢的。

佩琪: 那依靠HW和LEO,是如何导致数据不一致的呢,我觉得这个才是最要命的?

技术大佬 : 确实,如果多个分区之间的数据都不一致了,问题确实较大。咋们还是看图说话?

技术大佬问我,kafka是如何做到数据的高可靠的(下)

  1. 在min.isr=1的情况下,(A)和(B)同时宕机了
  2. (B) 先恢复,成为了leader,接受消息M3,HW变为了2
  3. (A)在恢复,然后截取消息日志,发现HW和LEO相同,就不截取了
  4. 此时在相同的消息位置1上,出现了不同的消息内容

佩琪: min.insync.replicas=1的情况下,确实恼火,有啥解决方法了?

技术大佬 : 有的,kafka 引入了Leader Epoch 的概念来解决这两个问题 。

技术大佬 : Leader Epoch 包含两部分数据。 一个是 epoch: 表示一个单调递增的版本号。每当leader 发生变更(比如重选变更)时,都会增加; 一个是 start offset: 在新 Leader Epoch 中写入日志的第一个偏移量的消息位置。

这部分数据 每个副本集都有,并且还写入了本地文件系统里。

佩琪: 那 Leader Epoch 是如何解决数据不一致的了?

技术大佬 : 咋们还是看图说话?

技术大佬问我,kafka是如何做到数据的高可靠的(下)

  1. (A)和(B)在宕机前;根据Leader Epoch 规则。Leader Epoch为0,start offset 为0
  2. 当 (B) 由于宕机重启后,(B) 成为了领导者;此时Leader Epoch为1,start offset为1
  3. (B) 接受了消息M3;
  4. (A)此时重启进行恢复;变成了follower,它在截断日志前会发送一个LeaderEpoch 的请求(参数里带上本分区的 leader epoch 0)给当前的领导者;
  5. 当前领导者 (B) 一查 Leader Epoch为0的log End offset (请求的leader epoch+1 的start offset )为1;然后返回给 (A)
  6. (A) 拿到返回值,发现leader epoch 为0的 log end offset为1 ,比自己本地的log end offset 2还小;那就以leader返回的为准吧;把1以及后面位置的日志都给截断了;这样在lead epoch为0时,(A)和(B)分区的日志数据保持了一致
  7. 为了追赶数据,folower(A) 再从leader(B)请求同步数据;把m3消息同步到本地中。最终 (A)和(B)保持了数据同步。

总结

在min.insync.replicas=1 + kafka只根据HW截断日志的情况下;主从分区,会存在已提交消息,在leader切换时;会丢失数据的情况;或者数据不一致的情况;

在min.insync.replicas=1的情况下,leader分区切换,导致已提交消息丢失,这个还能理解;谁让你设置的为1了;但是在这种情况下,发生leader 分区切换,导致数据不一致,却是不能允许的。

kafka已在0.11.0.0 版本中,通过引入 Leader Epoch的概念,解决了上述场景中的问题;降低了此种情况下,leader分区切换导致的数据丢失和不一致的问题。但在min.insync.replicas=1的情况下;仍然存在leader 分区切换后,已提交消息会丢失的问题。

原创不易,请 点赞,留言,关注,收藏 4暴击^^

参考资料:

cwiki.apache.org/confluence/…

转载自:https://juejin.cn/post/7329807974968492066
评论
请登录