极客时间Kafka - 13 Kafka 中的高水位和 Leader Epoch 机制

news2024/11/25 2:36:56

文章目录

      • 1. 什么是高水位?
      • 2. 高水位的作用
      • 3. 高水位更新机制
        • 1. Leader 副本高水位更新机制
        • 2. Follower 副本高水位更新机制
      • 4. 副本同步机制解析
      • 5. Leader Epoch

你可能听说过高水位(High Watermark),但不一定耳闻过 Leader Epoch。前者是 Kafka 中非常重要的概念,而后者是社区在 0.11 版本中新推出的,主要是为了弥补高水位机制的一些缺陷。鉴于高水位机制在 Kafka 中举足轻重,而且深受各路面试官的喜爱,今天我们就来重点说说高水位。当然,我们也会花一部分时间来讨论 Leader Epoch 以及它的角色定位。

1. 什么是高水位?

Kafka 的水位和位置信息绑定的,具体来说,它是用消息位移来表征的。另外,Kafka 源码使用的表述是高水位,因此,今天我也会统一使用“高水位”或它的缩写 HW 来进行讨论。值得注意的是,Kafka 中也有低水位(Low Watermark),它是与 Kafka 删除消息相关联的概念。

2. 高水位的作用

在 Kafka 中,高水位的作用主要有 2 个:

  • 定义消息可见性,即用来标识分区下的哪些消息是可以被消费者消费的。
  • 帮助 Kafka 完成副本同步。

下面这张图展示了多个与高水位相关的 Kafka 术语。我来详细解释一下图中的内容,同时澄清一些常见的误区。

在这里插入图片描述

我们假设这是某个分区 Leader 副本的高水位图。首先,请你注意图中的“已提交消息”和“未提交消息”。

什么是已提交的消息?当 Kafka 的若干个 Broker 成功地接收到一条消息并写入到日志文件后,它们会告诉生产者程序这条消息已成功提交。此时,这条消息在 Kafka 看来就正式变为“已提交”消息了。那为什么是若干个 Broker 呢?这取决于你对“已提交”的定义。你可以选择只要有一个 Broker 成功保存该消息就算是已提交,也可以是令所有 Broker 都成功保存该消息才算是已提交。

在分区高水位以下的消息被认为是已提交消息,反之就是未提交消息。消费者只能消费已提交消息,即图中位移小于 8 的所有消息。注意,这里我们不讨论 Kafka 事务,因为事务机制会影响消费者所能看到的消息的范围,它不只是简单依赖高水位来判断。它依靠一个名为 LSO(Log Stable Offset)的位移值来判断事务型消费者的可见性。

另外,需要关注的是,位移值等于高水位的消息也属于未提交消息。也就是说,高水位上的消息是不能被消费者消费的

图中还有一个日志末端位移的概念,即 Log End Offset,简写是 LEO。它表示副本写入下一条消息的位移值。注意,数字 15 所在的方框是虚线,这就说明,这个副本当前只有 15 条消息,位移值是从 0 到 14,下一条新消息的位移是 15。显然,介于高水位和 LEO 之间的消息就属于未提交消息。这也从侧面告诉了我们一个重要的事实,那就是:同一个副本对象,其高水位值不会大于 LEO 值

高水位和 LEO 是副本对象的两个重要属性。Kafka 所有副本都有对应的高水位和 LEO 值,而不仅仅是 Leader 副本。只不过 Leader 副本比较特殊,Kafka 使用 Leader 副本的高水位来定义所在分区的高水位。换句话说,分区的高水位就是其 Leader 副本的高水位

我们总说consumer无法消费未提交消息。这句话如果用以上名词来解读的话,应该表述为:consumer无法消费分区下leader副本中位移值大于分区HW的任何消息。这里需要特别注意分区HW就是leader副本的HW值

3. 高水位更新机制

现在,我们知道了每个副本对象都保存了一组高水位值和 LEO 值,但实际上,在 Leader 副本所在的 Broker 上,还保存了其他 Follower 副本的 LEO 值。我们一起来看看下面这张图。

Kafka有两套follower副本LEO (明白这个是搞懂后面内容的关键,因此请多花一点时间来思考):一套LEO保存在follower副本所在broker的副本管理机中;另一套LEO保存在leader副本所在broker的副本管理机中——换句话说,leader副本机器上保存了所有的follower副本的LEO。

在这里插入图片描述

在这张图中,我们可以看到,Broker 0 上保存了某分区的 Leader 副本和所有 Follower 副本的 LEO 值,而 Broker 1 上仅仅保存了该分区的某个 Follower 副本。Kafka 把 Broker 0 上保存的这些 Follower 副本又称为远程副本。Kafka 副本机制在运行过程中,会更新 Broker 1 上 Follower 副本的高水位和 LEO 值,同时也会更新 Broker 0 上 Leader 副本的高水位和 LEO 以及所有远程副本的 LEO,但它不会更新远程副本的高水位值,也就是我在图中标记为灰色的部分。

为什么要在 Broker 0 上保存这些远程副本呢?其实,它们的主要作用是,帮助 Leader 副本确定其高水位,也就是分区高水位

为了帮助你更好地记忆这些值被更新的时机,我做了一张表格。只有搞清楚了更新机制,我们才能开始讨论 Kafka 副本机制的原理,以及它是如何使用高水位来执行副本消息同步的。

  • Broker 0上的Leader副本LEO:Leader副本接收到生产者发送的消息,写入到本地磁盘后,就会更新其LEO值。
  • Broker 0上的Leader副本HW:主要有两个更新时机,一个是Leader副本更新其LEO之后;另一个是更新完远程副本LEO之后。具体的算法是取Leader副本和所有与Leader副本同步的远程副本LEO中的最小值
  • Broker 0上的远程副本LEO:Follow副本从Leader副本拉取消息时,会告诉Leader副本从哪个位移处开始拉取,Leader副本会使用这个位移值更新远程副本的LEO。
  • Broker 1上的Follower副本LEO:Follower副本从Leader副本拉取消息后,会更新其LEO值。
  • Broker 1上的Follower副本HW:Follower副本更新完LE之后,会比较其LEO值与Leader副本发来的高水位值,并用两者的最小值更新它自己的高水位。

在这里,我稍微解释一下,什么叫与 Leader 副本保持同步。判断的条件有两个:

① 该远程 Follower 副本在 ISR 中。

② 该远程 Follower 副本 LEO 值落后于 Leader 副本 LEO 值的时间,不超过 Broker 端参数 replica.lag.time.max.ms 的值。如果使用默认值的话,就是不超过 10 秒。

这两个条件好像是一回事,因为目前某个副本能否进入 ISR 就是靠第 2 个条件判断的。但有些时候,会发生这样的情况:即 Follower 副本已经“追上”了 Leader 的进度,却不在 ISR 中,比如某个刚刚重启回来的副本。如果 Kafka 只判断第 1 个条件的话,就可能出现某些副本具备了“进入 ISR”的资格,但却尚未进入到 ISR 中的情况。此时,分区高水位值就可能超过 ISR 中副本 LEO,而高水位 > LEO 的情形是不被允许的。

下面,我们分别从 Leader 副本和 Follower 副本两个维度,来总结一下高水位和 LEO 的更新机制。

1. Leader 副本高水位更新机制

处理生产者请求的逻辑:

  • 写入消息到本地磁盘。

  • 更新分区高水位值。

    • 获取 Leader 副本所在 Broker 端保存的所有远程副本 LEO 值{LEO-1,LEO-2,……,LEO-n}。
    • 获取 Leader 副本高水位值:currentHW。
    • 更新 currentHW = min(currentHW, LEO-1,LEO-2,……,LEO-n)。

处理 Follower 副本拉取消息的逻辑 :

  • 读取磁盘(或页缓存)中的消息数据。
  • 使用 Follower 副本发送请求中的位移值更新远程副本 LEO 值。
  • 更新分区高水位值(具体步骤与处理生产者请求的步骤相同)。

2. Follower 副本高水位更新机制

从 Leader 拉取消息的处理逻辑:

  • 写入消息到本地磁盘。
  • 更新 LEO 值。
  • 更新高水位值。
    • 获取 Leader 发送的高水位值:currentHW。
    • 获取步骤 2 中更新过的 LEO 值:currentLEO。
    • 更新高水位为 min(currentHW, currentLEO)。

4. 副本同步机制解析

搞清楚了这些值的更新机制之后,我来举一个实际的例子,说明一下 Kafka 副本同步的全流程。该例子使用一个单分区且有两个副本的主题。当生产者发送一条消息时,Leader 和 Follower 副本对应的高水位是怎么被更新的呢?我给出了一些图片,我们一一来看。

首先是初始状态。下面这张图中的 remote LEO 就是刚才的远程副本的 LEO 值。在初始状态时,所有值都是 0。

在这里插入图片描述

当生产者给主题分区发送一条消息后,状态变更为:

在这里插入图片描述

此时,Leader 副本成功将消息写入了本地磁盘,故 LEO 值被更新为 1。Follower 再次尝试从 Leader 拉取消息。和之前不同的是,这次有消息可以拉取了,因此状态进一步变更为:

在这里插入图片描述

这时,Follower 副本也成功地更新 LEO 为 1。此时,Leader 和 Follower 副本的 LEO 都是 1,但各自的高水位依然是 0,还没有被更新。它们需要在下一轮的拉取中被更新,如下图所示:

在这里插入图片描述

在新一轮的拉取请求中,由于位移值是 0 的消息已经拉取成功,因此 Follower 副本这次请求拉取的是位移值 =1 的消息。Leader 副本接收到此请求后,更新远程副本 LEO 为 1,然后更新 Leader 高水位为 1。做完这些之后,它会将当前已更新过的高水位值 1 发送给 Follower 副本。Follower 副本接收到以后,也将自己的高水位值更新成 1。至此,一次完整的消息同步周期就结束了。事实上,Kafka 就是利用这样的机制,实现了 Leader 和 Follower 副本之间的同步。

5. Leader Epoch

故事讲到这里似乎很完美,依托于高水位,Kafka 既界定了消息的对外可见性,又实现了异步的副本同步机制。不过,我们还是要思考一下这里面存在的问题。

从刚才的分析中,我们知道,Follower 副本的高水位更新需要一轮额外的拉取请求才能实现。如果把上面那个例子扩展到多个 Follower 副本,情况可能更糟,也许需要多轮拉取请求。也就是说,Leader 副本高水位更新和 Follower 副本高水位更新在时间上是存在错配的。这种错配是很多“数据丢失”或“数据不一致”问题的根源。基于此,社区在 0.11 版本正式引入了 Leader Epoch 概念,来规避因高水位更新错配导致的各种不一致问题。

所谓 Leader Epoch,我们大致可以认为是 Leader 版本。它由两部分数据组成:

① Epoch。一个单调增加的版本号。每当副本领导权发生变更时,都会增加该版本号。小版本号的 Leader 被认为是过期 Leader,不能再行使 Leader 权力。

② 起始位移(Start Offset)。Leader 副本在该 Epoch 值上写入的首条消息的位移。

我举个例子来说明一下 Leader Epoch。假设现在有两个 Leader Epoch<0, 0> 和 <1, 120>,那么,第一个 Leader Epoch 表示版本号是 0,这个版本的 Leader 从位移 0 开始保存消息,一共保存了 120 条消息。之后,Leader 发生了变更,版本号增加到 1,新版本的起始位移是 120。

Kafka Broker 会在内存中为每个分区都缓存 Leader Epoch 数据,同时它还会定期地将这些信息持久化到一个 checkpoint 文件中。当 Leader 副本写入消息到磁盘时,Broker 会尝试更新这部分缓存。如果该 Leader 是首次写入消息,那么 Broker 会向缓存中增加一个 Leader Epoch 条目,否则就不做更新。这样,每次有 Leader 变更时,新的 Leader 副本会查询这部分缓存,取出对应的 Leader Epoch 的起始位移,以避免数据丢失和不一致的情况。

接下来,我们来看一个实际的例子,它展示的是 Leader Epoch 是如何防止数据丢失的。请先看下图。

在这里插入图片描述

我稍微解释一下,单纯依赖高水位是怎么造成数据丢失的。开始时,副本 A 和副本 B 都处于正常状态,A 是 Leader 副本。某个使用了默认 acks 设置的生产者程序向 A 发送了两条消息,A 全部写入成功,此时 Kafka 会通知生产者说两条消息全部发送成功。

现在我们假设 Leader 和 Follower 都写入了这两条消息,而且 Leader 副本的高水位也已经更新了,但 Follower 副本高水位还未更新——这是可能出现的。还记得吧,Follower 端高水位的更新与 Leader 端有时间错配。倘若此时副本 B 所在的 Broker 宕机,当它重启回来后,副本 B 会执行日志截断操作,将 LEO 值调整为之前的高水位值,也就是 1。这就是说,位移值为 1 的那条消息被副本 B 从磁盘中删除,此时副本 B 的底层磁盘文件中只保存有 1 条消息,即位移值为 0 的那条消息。

当执行完截断操作后,副本 B 开始从 A 拉取消息,执行正常的消息同步。如果就在这个节骨眼上,副本 A 所在的 Broker 宕机了,那么 Kafka 就别无选择,只能让副本 B 成为新的 Leader,此时,当 A 回来后,需要执行相同的日志截断操作,即将高水位调整为与 B 相同的值,也就是 1。这样操作之后,位移值为 1 的那条消息就从这两个副本中被永远地抹掉了。这就是这张图要展示的数据丢失场景。

严格来说,这个场景发生的前提是Broker 端参数 min.insync.replicas 设置为 1。此时一旦消息被写入到 Leader 副本的磁盘,就会被认为是“已提交状态”,但现有的时间错配问题导致 Follower 端的高水位更新是有滞后的。如果在这个短暂的滞后时间窗口内,接连发生 Broker 宕机,那么这类数据的丢失就是不可避免的。

现在,我们来看下如何利用 Leader Epoch 机制来规避这种数据丢失。我依然用图的方式来说明。

在这里插入图片描述

场景和之前大致是类似的,只不过引用 Leader Epoch 机制后,Follower 副本 B 重启回来后,需要向 A 发送一个特殊的请求去获取 Leader 的 LEO 值。在这个例子中,该值为 2。当获知到 Leader LEO=2 后,B 发现该 LEO 值不比它自己的 LEO 值小,而且缓存中也没有保存任何起始位移值 > 2 的 Epoch 条目,因此 B 无需执行任何日志截断操作。这是对高水位机制的一个明显改进,即副本是否执行日志截断不再依赖于高水位进行判断。

现在,副本 A 宕机了,B 成为 Leader。同样地,当 A 重启回来后,执行与 B 相同的逻辑判断,发现也不用执行日志截断,至此位移值为 1 的那条消息在两个副本中均得到保留。后面当生产者程序向 B 写入新消息时,副本 B 所在的 Broker 缓存中,会生成新的 Leader Epoch 条目:[Epoch=1, Offset=2]。之后,副本 B 会使用这个条目帮助判断后续是否执行日志截断操作。这样,通过 Leader Epoch 机制,Kafka 完美地规避了这种数据丢失场景。

总结:

高水位在界定 Kafka 消息对外可见性以及实现副本机制等方面起到了非常重要的作用,但其设计上的缺陷给 Kafka 留下了很多数据丢失或数据不一致的潜在风险。为此,社区引入了 Leader Epoch 机制,尝试规避掉这类风险。事实证明,它的效果不错,在 0.11 版本之后,关于副本数据不一致性方面的 Bug 的确减少了很多。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/86726.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vxe-table 实现表格填写自动计算且限制数值的复杂操作

vxe-table 实现表格填写自动计算且限制数值复杂操作 效果 演示思路 输入框设置最大值 :max"row.max"输入框调用方法blur"updateFooterEvent(row, $event)" input" if (row[item.field] > row.max) { row[item.field] row.max; } " 上代码…

我们是如何追逐元宇宙、XR等“概念股”浪潮的?

作者&#xff1a;金擘(渚薰) 1.今年我们迈出的第一步 随着淘宝人生小屋项目的正式上线&#xff0c;淘宝人生今年的元宇宙规划初步成型。 加上在 S1 同淘宝直播团队的合作上线的 Disney 毛毛狂欢馆&#xff0c;我们也正式迈出了“元宇宙”技术的第一步。 今年是淘宝人生上线 3…

数智技术,企业绿色低碳转型的催化剂?大咖说新一期每周推荐来袭!

“双碳”战略下&#xff0c;企业会遇到哪些机遇和挑战&#xff1f;中小企业如何实现绿色转型&#xff1f;数字化又在其中发挥了怎样的作用&#xff1f; 介绍&#xff1a; 阿里云能耗云总经理 周文闻 施耐德电气首席数字化设计师 毛春景 “双碳”战略下&#xff0c;企业会遇到…

你写过哪些有趣的python?(附零基础学习资料)

前言 某网站上有个浏览超过400万的问题&#xff1a;可以用 Python 编程语言做哪些神奇好玩的事情&#xff1f; 我先举一个很不专业的栗子… 然后再找几个人抬一堆例子来… 不是很稀饭《复联》嘛&#xff0c;看了《复联4》&#xff0c;就用50行Python代码做了这些&#xff1a;…

Word控件Spire.Doc 【超链接】教程(4):如何修改Word文档中的超文本

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

【leetcode】从前序与中序遍历序列构造二叉树

一、题目描述 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 示例1&#xff1a; 输入: preorder [3,9,20,15,7], inorder [9,3,15,20,7] 输出:…

rk3399-uboot2017-增加串口通信

一、主要还是解决这个问题&#xff0c;最后没办法&#xff0c;只能进行串口通信&#xff0c;来识别屏幕的类型了。 基本步骤如下&#xff1a; 1. uboot阶段发送串口指令&#xff0c;等待串口回复数据&#xff0c;根据数据识别屏幕类型 2.在bootargs增加一个自定义的参数&…

一个完整的项目是如何开展的:对项目生涯的总结

我正在参加「掘金启航计划」 变量的类型指的是变量的特性或特征&#xff0c;比如表示数字类型、文本类型、集合类型等&#xff0c;表示的是一类数据。 Dart提供以下的内置类型&#xff1a; 数字&#xff1a;int, double (整型(表示整数)&#xff0c;浮点型(表示小数))布尔&a…

程序员如何平衡主业和副业?

什么是副业&#xff1f; 对于副业的定义&#xff0c;每个人都有自己的见解。不过对大部分人来说&#xff0c;副业相对于主业而言&#xff0c;就是工作日朝九晚五的工作称为主业&#xff0c;其他时间做的赚钱的项目或者工作可以称之为副 副业可以是写文章、拍视频、打代码&…

干扰管理学习日志8-------多用户联合_资源卸载_功率分配_计算资源分配

目录一、文章概述二、系统模型环境三、理论模型1.系统目标2.约束条件3.公式推导四、算法设计1.上行链路功率分配策略(1)任务目标(2)伪代码2.中央服务器算力分配策略3.任务卸载策略(1)任务目标(2)卸载集缩小条件(3)卸载集扩充条件(4)策略(5)伪代码五、性能表征本文是对论文《Mul…

[Linux]----初始网络

文章目录前言一、计算机网络的背景重新看待计算机结构网络发展认识"协议"二、网络协议初始软件分层协议分层OSI七层模型TCP/IP五层(四层)模型三、网络传输的基本流程网络和操作系统之间的关系局域网通信的原理四、数据包的封装和分用五、网络中的地址管理认识IP地址认…

2004-2020年全国30省工业污染治理完成投资数据

2004-2020年全国30省工业污染治理完成投资数据 1、时间&#xff1a;2004-2020年 2、范围&#xff1a;包括全国30个省&#xff0c;不含西藏 3、来源&#xff1a;国家统计J 4、缺失情况说明&#xff1a;无缺失 5、指标说明&#xff1a; 目前虽然采取了一系列环境规制相关政…

[附源码]Python计算机毕业设计SSM基于Web学术会议投稿管理系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

二元灰狼优化(BGWO)应用于特征选择任务(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 特征选择是当前信息领域,尤其是模式识别领域的研究热点。该代码演示了BGWO如何使用基准数据集Main解决特征选择问题。 &#…

python国际化课程capstone(ML预测ACM队员获奖概率)

目录 前言 原始数据集 爬虫部分 爬取每个队员在buct做题数量 爬取每个队员codeforces的最高分&#xff0c;注册时间&#xff0c;解题数量 爬取每个队员有效做题时间 数据处理部分 模型部分 Linear Regression XGBregressiongridsearchCV调参 Random Forset 前言 刚…

Redis框架(九):大众点评项目 缓存工具封装

大众点评项目 缓存工具封装需求&#xff1a;缓存工具封装业务实现代码总览总结SpringCloud章节复习已经过去&#xff0c;新的章节Redis开始了&#xff0c;这个章节中将会回顾Redis实战项目 大众点评 主要依照以下几个原则 基础实战的Demo和Coding上传到我的代码仓库在原有基础…

视频直播技术干货:一文读懂主流视频直播系统的推拉流架构、传输协议等

1、引言 随着移动网络网速的提升与资费的降低&#xff0c;视频直播作为一个新的娱乐方式已经被越来越多的用户逐渐接受。特别是最近这几年&#xff0c;视频直播已经不仅仅被运用在传统的秀场、游戏类板块&#xff0c;更是作为电商的一种新模式得到迅速成长。 本文将通过介绍实时…

爆火Chatgpt注册完全指南

1 chatgpt 简介 ChatGPT是一种语言模型&#xff0c;它被训练来对对话进行建模。它能够通过学习和理解人类语言来进行对话&#xff0c;并能够生成适当的响应。ChatGPT使用了一种叫做Transformer的神经网络架构&#xff0c;这是一种用于处理序列数据的模型&#xff0c;能够在输入…

第33篇 网络(三)FTP(一)

导语 上一节我们讲述了HTTP的编程&#xff0c;这一节讲述与其及其相似的FTP的编程。FTP即FileTransfer Protocol&#xff0c;也就是文件传输协议。FTP的主要作用&#xff0c;就是让用户连接上一个远程计算机&#xff0c;查看远程计算机有哪些文件&#xff0c;然后把文件从远程…

STM32F4 | STM32CubeMX 图形配置工具

文章目录一、STM32CubeMX 简介二、STM32CubeMX 运行环境搭建1.Java环境安装2.STM32CubeMX 图形化工具安装三、使用 STM32CubeMX 工具配置工程模板1.工程初步建立和保存2.RCC 设置3.时钟系统&#xff08;时钟树&#xff09;配置4.GPIO 功能引脚配置5.生成工程源码6.编写用户程序…