理想论坛_专业20年的财经股票炒股论坛交流社区 - 股票论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2694|回复: 0

图解 Kafka 水印备份机制

[复制链接]

9650

主题

9650

帖子

2万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
28966
发表于 2019-12-27 14:13 | 显示全部楼层 |阅读模式
高可用是很多散布式系统中必备的特征之一,Kafka 日志的高可用是经过基于 leader-follower 的多副本同步实现的,每个分区下有多个副本,其中只要一个是 leader 副本,供给发送和消耗消息,此外都是 follower 副本,不停地发送 fetch 请求给 leader 副本以同步消息,假如 leader 在全部集群运转进程中不发生故障,follower 副本不会起到任何感化,题目就在于任何系统都不能保证其安定运转,当 leader 副当地址的 broker 崩溃以后,其中一个 follower 副本就会成为该分区下新的 leader 副本,那末题目来了,在选为新的 leader 副本时,会致使消息丧失大要离散吗?Kafka 是怎样打点 leader 副本变更时消息不会出错?以及 leader 与 follower 副本之间的数据同步是怎样举行的?带着这几个题目,我们接着往下看,一路揭开 Kafka 水印备份的机密面纱。
水印关连概念

在讲解水印备份之前,我们必必要先搞清楚几个关键的术语以及它们的寄义,下面我用一张图来表现 Kafka 分区副本的位移信息:

如上图所示,绿色部分表现已完全备份的消息,抵消耗者可见,紫色部分表现未完全备份的消息,抵消耗者不偏见。
LEO(last end offset):日志末端位移,记载了该副本工具底层日志文件中下一条消息的位移值,副本写入消息的时候,会自动更新 LEO 值。
HW(high watermark):从名字可以晓得,该值叫高水印值,HW 必定不会大于 LEO 值,小于 HW 值的消息被以为是“已提交”或“已备份”的消息,并抵消耗者可见。
leader 会保存两个典范的 LEO 值,一个是自己的 LEO,另一个是 remote LEO 值,remote LEO 值就是 follower 副本的 LEO 值,意味着 follower 副本的 LEO 值会保存两份,一份保存到 leader 副本中,一份保存到自己这里。
remote LEO 值有什么用呢?
它是决议 HW 值巨细的关键,当 HW 要更新时,就会对照 LEO 值(也包含 leader LEO),取最小的那个做最新的 HW 值。
以下先容 LEO 和 HW 值的更新机制:
LEO 更新机制:

  • leader 副本本身的 LEO 值更新:在 Producer 消息发送过来时,即 leader 副本当前最新存储的消息位移位置 +1;
  • follower 副本本身的 LEO 值更新:从 leader 副本中 fetch 到消息并写到当地日志文件时,即 follower 副本当前同步 leader 副本最新的消息位移位置 +1;
  • leader 副本中的 remote LEO 值更新:每次 follower 副本发送 fetch 请求城市包含 follower 当前 LEO 值,leader 拿到该值就会实行更新 remote LEO 值。
leader HW 更新机制:
leader HW 更新分为故障时更新与一般时更新:
故障时更新:

  • 副本被选为 leader 副本时:当某个 follower 副本被选为分区的 leader 副本时,kafka 就会实行更新 HW 值;
  • 副本被踢出 ISR 时:假如某个副本追不上 leader 副本进度,大要地址 broker 崩溃了,致使被踢出 ISR,leader 也会检查 HW 值能否必要更新,究竟 HW 值更新只跟处于 ISR 的副本 LEO 有关系。
一般时更新:

  • producer 向 leader 副本写入消息时:在消息写入时会更新 leader LEO 值,是以必要再检查能否必要更新 HW 值;
  • leader 处置惩罚 follower FETCH 请求时:follower 的 fetch 请求会照顾 LEO 值,leader 会按照这个值更新对应的 remote LEO 值,同时也必要检查能否必要更新 HW 值。
follower HW 更新机制:

  • follower 更新 HW 发生在其更新 LEO 以后,每次 follower Fetch 响应体城市包含 leader 的 HW 值,然后比力当前 LEO 值,取最小的作为新的 HW 值。
图解水印备份进程

在了解了 Kafka 水印备份机制的关连概念以后,下面我用图来帮大家更好地明白 Kafka 的水印备份进程,假定某个分区有两个副本,min.insync.replica=1:

Step 1:leader 和 follower 副本处于初始化值,follower 副本发送 fetch 请求,由于 leader 副本没稀有据,是以不会举行同步利用;
Step 2:生产者发送了消息 m1 到分区 leader 副本,写入该条消息后 leader 更新 LEO = 1;
Step 3:follower 发送 fetch 请求,照顾当前最新的 offset = 0,leader 处置惩罚 fetch 请求时,更新 remote LEO = 0,对照 LEO 值最小为 0,所以 HW = 0,leader 副底细应消息数据及 leader HW = 0 给 follower,follower 写入消息后,更新 LEO 值,同时对照 leader HW 值,取最小的作为新的 HW 值,此时 follower HW = 0,这也意味着,follower HW 是不会超出 leader HW 值的。
Step 4:follower 发送第二轮 fetch 请求,照顾当前最新的 offset = 1,leader 处置惩罚 fetch 请求时,更新 remote LEO = 1,对照 LEO 值最小为 1,所以 HW = 1,此时 leader 没有新的消息数据,所以间接返回 leader HW = 1 给 follower,follower 对照当前最新的 LEO 值 与 leader HW 值,取最小的作为新的 HW 值,此时 follower HW = 1。
基于水印备份机制的一些缺点

从以上步伐可看出,leader 中保存的 remote LEO 值的更新总是必要额外一轮 fetch RPC 请求才华完成,这意味着在 leader 切换进程中,会存在数据丧失以及数据不齐截的题目,下面我用图来分析存在的题目:

  • 数据丧失

前面也说过,leader 中的 HW 值是在 follower 下一轮 fetch RPC 请求中完成更新的,如上图所示,有副本 A 和 B,其中 B 为 leader 副本,A 为 follower 副本,在 A 举行第二段 fetch 请求,并吸收到响应以后,此时 B 已经将 HW 更新为 2,假如这是 A 还没处置惩罚完响应就崩溃了,即 follower 没有实时更新 HW 值,A 重启时,会自动将 LEO 值调解到之前的 HW 值,即会举行日志截断,接着会向 B 发送 fetch 请求,但很不幸的是此时 B 也发生宕机了,Kafka 会将 A 推举为新的分区 Leader。当 B 重启后,会从 向 A 发送 fetch 请求,收到 fetch 响应后,拿到 HW 值,并更新当地 HW 值,此时 HW 被调解为 1(之前是 2),这时 B 会做日志截断,是以,offsets = 1 的消息被永久地删除了。
大要你会问,follower 副本为什么要举行日志截断?
这是由于消息会先记载到 leader,follower 再从 leader 中拉取消息举行同步,这就致使 leader LEO 会比 follower 的要大(ollower之间的offset也不尽类似,固然终极会齐截,但进程中会有不同),假定此时出现 leader 切换,有大要推举了一个 LEO 较小的 follower 成为新的 leader,这时该副本的 LEO 就会成为新的标准,这就会致使 follower LEO 值有大要会比 leader LEO 值要大的情况,是以 follower 在举行同步之前,必要从 leader 获得 LastOffset 的值(该值后背会有表白),假如 LastOffset 小于 当前 LEO,则必要举行日志截断,然后再从 leader 拉取数据实现同步。
大要你还会问,日志截断会不会形成数据丧失?
前面也说过,HW 值以上的消息是没有“已提交”或“已备份”的,是以消息也是抵消耗者不偏见,即这些消息差池用户作答应,也即是说从 HW 值截断日志,并不会致使数据丧失(答利用户范围内)。

  • 数据不齐截/离散

以上情况,必要满足以下其中一个条件才会发生:

  • 宕机之前,B 已不在 ISR 列表中,unclean.leader.election.enable=true,即答应非 ISR 中副本成为 leader;
  • B 消息写入到 pagecache,但尚未 flush 到磁盘。
分区有两个副本,其中 A 为 Leader 副本,B 为 follower 副本,A 已经写入两条消息,且 HW 更新到 2,B 只写了 1条消息,HW 为 1,此时 A 和 B 同时宕机,B 先重启,B 成为了 leader 副本,这时生产者发送了一条消息,保存到 B 中,由于此时分区只要 B,B 在写入消息时把 HW 更新到 2,就在这时候 A 重新启动,发现 leader HW 为 2,跟自己的 HW 一样,是以没有实行日志截断,这就形成了 A 的 offset=1 的日志与 B 的 offset=1 的日志纷歧样的现象。
leader epoch

为了处理 HW 更新机遇是异步迟误的,而 HW 又是决议日志能否备份乐成的标志,从而形成数据丧失和数据不齐截的现象,Kafka 引入了 leader epoch 机制,在每个副本日志目录下都建立一个 leader-epoch-checkpoint 文件,用于保存 leader 的 epoch 信息,以下,leader epoch 长这样:

它的格式为 (epoch offset),epoch指的是 leader 版本,它是一个单调递增的一个正整数值,每次 leader 变更,epoch 版本城市 +1,offset 是每一代 leader 写入的第一条消息的位移值,比如:
  1. (0, 0)(1, 300)
复制代码
以上第二个版本是从位移300起头写入消息,意味着第一个版本写入了 0-299 的消息。
leader epoch 具体的工作机制以下:
1)当副本成为 leader 时:
这时,假如此时生产者有新消息发送过来,会首先新的 leader epoch 以及 LEO 增加到 leader-epoch-checkpoint 文件中。
2)当副本酿成 follower 时:

  • 发送 LeaderEpochRequest 请求给 leader 副本,该请求包含了 follower 中最新的 epoch 版本;
  • leader 返回给 follower 的响应中包含了一个 LastOffset,假如 follower last epoch = leader last epoch,则 LastOffset = leader LEO,否则取大于 follower last epoch 中最小的 leader epoch 的 start offset 值,举个例子:假定 follower last epoch = 1,此时 leader 有 (1, 20) (2, 80) (3, 120),则 LastOffset = 80;
  • follower 拿到 LastOffset 以后,会对照当前 LEO 值能否大于 LastOffset,假如当前 LEO 大于 LastOffset,则从 LastOffset 截断日志;
  • follower 起头发送 fetch 请求给 leader 连结消息同步。
基于 leader epoch 的工作机制,我们接下来看看它是怎样打点水印备份缺点的:
(1)打点数据丧失:

如上图所示,A 重启以后,发送 LeaderEpochRequest 请求给 B,由于 B 还没追加消息,此时 epoch = request epoch = 0,是以返回 LastOffset = leader LEO = 2 给 A,A 拿到 LastOffset 以后,发现即是当前 LEO 值,故不用举行日志截断。就在这时 B 宕机了,A 成为 leader,在 B 启动归来后,会反复 A 的行动,一样不必要举行日志截断,数据没有丧失。
(2)打点数据不齐截/离散

如上图所示,A 和 B 同时宕机后,B 先重启归来成为分区 leader,这时候生产者发送了一条消息过来,leader epoch 更新到 1,此时 A 启动归来后,发送 LeaderEpochRequest(follower epoch = 0) 给 B,B 判定 follower epoch 不即是 最新的 epoch,因而找到大于 follower epoch 最小的 epoch = 1,即 LastOffset = epoch start offset = 1,A 拿到 LastOffset 后,判定小于当前 LEO 值,因而从 LastOffset 位置举行日志截断,接着起头发送 fetch 请求给 B 起头同步消息,制止了消息不齐截/离散的题目。
更多出色文章请关注作者保护的公众号「后端进阶」,这是一个专注后端关连技术的公众号。
关注公众号并复兴「后端」免费支付后端关连电子书籍。
接待分享,转载请保存出处。


免责声明:假如加害了您的权益,请联系站长,我们会实时删除侵权内容,感谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|理想论坛_专业20年的财经股票炒股论坛交流社区 - 股票论坛

GMT+8, 2020-7-3 06:26 , Processed in 0.164184 second(s), 29 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表