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

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

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

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

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

技术大佬 : 准确说是在 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,是如何导致数据不一致的呢,我觉得这个才是最要命的?

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

  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 是如何解决数据不一致的了?

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

  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 分区切换后,已提交消息会丢失的问题。

如果要提高broker端消息的可靠性,可参考:《kafka 消息"零丢失"》

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

参考资料:

cwiki.apache.org/confluence/...

相关推荐
William Dawson2 分钟前
【Vue 3 + Element Plus 实现产品标签的动态添加、删除与回显】
前端·javascript·vue.js
拉不动的猪11 分钟前
项目基础搭建时的一些基本注意点
前端·javascript·面试
蕉君桑20 分钟前
vue2使用vue-echarts
前端·vue.js·echarts
bobz96536 分钟前
qemu 对于外部网卡的配置方式
后端
runnerdancer38 分钟前
React+Vite+Typescript项目脚手架模版
前端
Code额1 小时前
ECMAScript 6 新特性(二)
前端·javascript·ecmascript
_一条咸鱼_1 小时前
Android大厂面试秘籍: View 相关面试题深入分析
android·面试·android jetpack
_一条咸鱼_1 小时前
Android 大厂面试秘籍:Hilt 框架的测试支持模块(八)
android·面试·kotlin
techdashen1 小时前
Rust主流框架性能比拼: Actix vs Axum vs Rocket
开发语言·后端·rust
普通网友1 小时前
内置AI与浏览器的开源终端Wave Terminal安装与远程连接内网服务器教程
开发语言·后端·golang