[转帖]Kafka可靠性之HW与Leader Epoch
《深入理解Kafka:核心设计与实现原理》是基于2.0.0版本的书
在这本书中,终于看懂了笔者之前提过的几个问题
准备知识
1、leader里存着4个数据:leader_LEO、leader_HW、remote_LEO集合、remote_HW集合
2、follower里只保存自身的:follower_LEO、follower_HW
HW和LEO更新过程
假设:
1个leader 和 2个follower
此时:leader_LEO = 5、leader_HW = 0、所有 follower 的 follower_LEO = 0、follower_HW = 0
同步开始
1、follower向leader发送fetch请求,来拉取消息,这个fetch请求会带上各自的follower_LEO
(先省略leader处理fetch请求的过程)
2、leader接收fetch请求后,处理并返回,这个fetch请求的响应会带上 leader_HW
3、follower拿到了fetch请求的response,同步消息数据,更新自己的 follower_LEO
(假设此时 这2个 follower_HW 分别为3和4)
4、接下来计算一下 follower_HW 并更新
公式:follower_HW = min(leader_HW,follower_LEO)
所以 两个follower此时的 follower_HW 都是 min(0,0) = 0
5、follower再次发送fetch请求,并带上各自的 follower_LEO
6、leader处理fetch请求过程如下
把这2个 follower_LEO 加上自己的 leader_LEO,取最小值作为新的 leader_HW
公式:leader_HW = min(leader_LEO,RemoteIsrLEO)
(RemoteIsrLEO:ISR中的所有follower的follower_LEO)
leader_HW = min(l5,3,4) = 3
7、leader_HW = 3 被 fetch请求的response带上,返回
8、2个follower收到response后,依然是,同步消息数据,更新 follower_LEO,更新 follower_HW
(假设此时 这2个 follower_HW 分别更新至 6和8)
follower_HW1 = min(3,6) = 3
follower_HW2 = min(3,8) = 3
(leader在上面几张图分别等于5、10、15、20的意思是,在上述过程中,leader一直接收着producer的消息数据)、
为什么follower_HW = min(leader_HW,follower_LEO) ?
因为这个follower没说是哪里的follower。
当然对于ISR中的follower根本不必多此一举,其实直接 follower_HW = leader_HW 就可以
但是对于OSR中正在拼命追赶leader的follower,它的follower_LEO可能小于leader_HW
所以公式为什么是公式,原因就在这。

如图为笔者的理解。
至于很多博客,说什么谁大谁小,谁一定小于谁,谁一定小于等于谁。
不加限定条件你说NM呢?HW和LEO多了去了,谁知道你说的是哪个和哪个比?
HW更新的问题
大家仔细观察上图

这幅图展示的是follower接收到了fetch请求的response,更新了各自的follower_LEO和follower_HW
问题在哪?
leader 中有数据 offset 0-9
follower1 中有数据 offset 0-2
follower2 中有数据 offset 0-3
现在是不是offset 0-2这3个消息是ISR中所有replica中都有了,这是不是完全同步了。
既然是,为什么HW不更新成3?offset 0-2这3条数据此时,按理说就应该可以被consumer消费了。
但是并没有,HW更新为3是下一次fetch请求响应都结束后,leader_HW和follower_HW才更新成3的。
remote_LEO、leader_HW、follower_HW的更新发生于follower_LEO更新后的第二轮fetch请求。
说人话就是:
消息数据已经完全同步了,但是HW的更新比消息晚了一次请求。
也可以理解为HW的更新是异步的。
因为按照我们的认知,既然消息已经在ISR完全同步成功后,应该立马可以消费,或者说,消息和HW应该同步更新。
也正因为不是这样的,所以才会出现数据丢失和数据一致性的问题。
HW的截断
假设此时的状态是 HW= 5,即:offset = 0~4的消息对于consumer可见

此时leader宕机,follower1选举为leader,leader重启成为follower。
原则就是:一切以leader为准,新follower此时会根据之前 HW 位置进行日志截断,并重新发起fetch请求追赶。
(这个值会存入本地的复制点文件 replication-offset-checkpoint )
那么新follower最多能追到offset=6,这是不是说明offset=7的消息就丢了。
不是的,这种情况就是正常的情况,因为offset=7这个消息并未“完全同步”,这个消息根本没有写入成功,何谈丢消息。
如图,如果offset=5的消息丢了,那才是真正的丢消息。
HW机制之丢失消息
在 0.11.0.0 版本之前, Kafka使用的是基于HW的同步机制,
但这样有可能出现数据丢失或leader副本和follower副本数据不一致的问题。
官方已经自己给出例子说明了
简言之,既然消息数据和HW是异步更新的,
那么你一定能找出某种场景:让已经实现“完全同步”但HW没来得及更新的消息丢失。
1、此时leader收到fetch请求,没有消息要同步了,返回leader_HW=2
follower接到response,再更新follower_HW = 2就OK了。

删除线部分并没有发生,而是follower宕机了,此时再次重启follower,重启之后会根据之前 HW 位置进行日志截断 。

好的,此时follower上的offset=1的消息没了。
2、follower截断日志后,应该去追赶leader,先一次fetch,从新把offset=1的消息拿过来,再一次fetch,把HW更新为2
删除线部分依然没发生,而是leader宕机了,follower成了新leader,重启旧leader成为了follower。

3、follower_HW不能比leader_HW 大,必须以leader为准,所以还会做一次日志截断,以此将follower_HW调整为 1

至此,offset=1的消息就被玩没了。
HW机制之数据不一致
场景:leader有 2 条消息,且 HW 和 LEO 都为 2, follower有 1 条消息,且 HW 和 LEO 都为 1

1、leader和follower同时宕机,follower率先复苏,成为新leader,并接收一个消息m
并将LEO和HW更新至 2 (假设所有场景中的 min.insync.replicas 参数配置为 1)

2、旧leader重启,成为follower,需要根据 HW 截断日志及发送 FetchRequest 至新leader ,
不过此时HW相等,那么就可以不做任何调整了。

至此,数据就不一致了。
leader epoch 方案
Kafka 从 0.11.0.0 开始引入了 leader epoch 的概念,
笔者总结的核心思路
1、在需要截断数据的时候使用 leader epoch 作为参考依据而不是原本的 HW
2、leader epoch 把他比喻成 时代、朝代 都可以,就是为了比较,follower和leader是不是处于一个朝代的
(方唐镜:包大人你好大的官威啊,拿前朝的剑斩本朝的官!)
3、如果处于同时代,follower的LEO对比leader的LEO,follower落后就不用截断,超过就自行了断。
4、如果处于不同时代,// TODO
存储位置和segment是一起的,文件名:leader-epoch-checkpoint
文件内容分两列
第一列:leader的版本号,每当leader出现变更就会追加一条记录,版本号+1
第二列:这个leader上任后,写入的第一条数据的offset
-
# 说明leader的0代目,写下了offset 0~99 = 100 条消息,之后当场去世
-
# 1代目,从offset = 100 开始写入,目前还没死
-
0 0
-
1 100
leader epoch 的作用
在日志截断之前,加一层判断是否有必要截断。而这个判断的依据就是leader epoch
当replica成为leader时
收到生产者发来的第一条消息时,会将新的epoch和当前LEO添加到leader-epoch-checkpoint文件中。
当replica成为follower时
(epoch太别扭了,以下都用version代替)
0、先不急着截断
1、向leader发送请求,带上follower当前本地的最新epoch,也就是文件中的那个最大版本号 follower_max_version
2、leader接收请求,需要进行一下计算,并返回一个last_offset值
如果 follower_max_version = leader_max_version,last_offset = leader_LEO
如果不相等,leader就取 follower_max_version+1 这个版本对应的start_offset 当作 last_offset
3、follower拿到response里的 last_offset 进行判断
如果 last_offset < follower_LEO,需要进行截断
否则不需要
4、开始fetch请求
笔者的疑问
很奇怪,说到last_offset的判断时,书里也只说了相等或不相等,很多看似华丽的博客完全都是copy书上的,一点没改。
按理来说,不应该区分以下谁大谁小么?
不相等,为什么能保证一定能取到 follower_max_version+1 的数据呢?
会不会有的follower的follower_max_version比leader中的还大,这个不得而知。
【如果不相等,leader就取 follower_max_version+1 这个版本对应的start_offset 】
你怎么就知道 follower_max_version 一定比leader的小呢?
———————————————以下是笔者的假设———————————————————
假设,一个leader,目前为止还没写入过消息,所有replica的leader epoch 都是一样的,等于2。
此时,这个leader收到了producer的一条数据,记录了leader epoch,假设为3。
然后他马上宕机,此时其他的follower的 leader epoch还都是2(这就是问题所在,这个epoch到底是怎么同步的)
有一个follower选举为leader,且一直没有producer发消息,这个新leader的 leader epoch 也是2,
这是旧的leader重启成为follower,那么此时是不是follower的leader epoch比新leader的大了呢?
——————————————————————————————————————————
笔者仔细看了官方的文档,借助谷歌翻译,大概能知道为了保持leader epoch的同步,Kafka一定做了某些处理方案,
但是具体的看不懂。
而对于,两本书中都提到的“不等于”、“否则”,哎,不等于到底是大于还是小于啊?
如果在leader中一定能找到 follower_max_version+1 的 epoch,那为什么用不等于这种模棱两可的表达呢?
[转帖]Kafka可靠性之HW与Leader Epoch的更多相关文章
- Kafka设计解析(二十一)Kafka水位(high watermark)与leader epoch的讨论
转载自 huxihx,原文链接 Kafka水位(high watermark)与leader epoch的讨论 本文主要讨论0.11版本之前Kafka的副本备份机制的设计问题以及0.11是如何解决的. ...
- Kafka水位(high watermark)与leader epoch的讨论
~~~这是一篇有点长的文章,希望不会令你昏昏欲睡~~~ 本文主要讨论0.11版本之前Kafka的副本备份机制的设计问题以及0.11是如何解决的.简单来说,0.11之前副本备份机制主要依赖水位(或水印) ...
- kafka入门之broker-水印和leader epoch
每个kafka副本对象都持有2个重要的属性:日志末端位移LEO,高水印HW Kafka对leader副本和follower副本的LEO更新机制是不同的,后面我们会详细讨论. Kafka对leader副 ...
- RabbitMQ和Kafka可靠性
RabbitMQ和Kafka可靠性 https://www.cnblogs.com/haolujun/p/9641840.html 我们通过前文知道,RabbitMQ的队列分为master queue ...
- kafka数据一致性(HW只能保证副本之间的数据一致性,并不能保证数据不丢失ack或者不重复。)
数据一致性问题:消费一致性和存储一致性 例如:一个leader 写入 10条数据,2个follower(都在ISR中),F1.F2都有可能被选为Leader,例如选F2 .后面Leader又活了.可能 ...
- leader epoch
更多内容,前往 IT-BLOG leader epoch 代表 Leader 的纪元信息(epoch),初始值为0.每当 Leader 变更一次,leader epoch 的值就会加1,相当于为 Le ...
- Kafka中的HW、LEO、LSO等分别代表什么?
HW . LEO 等概念和上一篇文章所说的 ISR有着紧密的关系,如果不了解 ISR 可以先看下ISR相关的介绍. HW (High Watermark)俗称高水位,它标识了一个特定的消息偏移量(of ...
- Kafka可靠性的思考
首先kafka的throughput 很牛逼,参考:http://engineering.linkedin.com/kafka/benchmarking-apache-kafka-2-million- ...
- kafka备份机制——zk选举leader,leader在broker里负责备份
Kafka架构 如上图所示,一个典型的kafka集群中包含若干producer(可以是web前端产生的page view,或者是服务器日志,系统CPU.memory等),若干broker(Kafka支 ...
- [转帖]kafka 如何保证数据不丢失
kafka 如何保证数据不丢失 https://www.cnblogs.com/MrRightZhao/p/11498952.html 一般我们在用到这种消息中件的时候,肯定会考虑要怎样才能保证数 ...
随机推荐
- 打造 VSCode 高效 C++ 开发环境的必备插件
工欲善其事,必先利其器 C++ clangd:代码补全.跳转.clang-tidy 检查,自带 clang-format CodeLLDB:LLVM 的调试器(类比 GDB) CMake CMake ...
- 【华为云技术分享】STM32L476移植华为LiteOS系列教程------背景知识 1
一.这篇文章想向大家说明一个问题,我们开发单片机的本质是什么? 在最早的开发中,我们没有Keil.IAR等等一系列好用的单片机集成开发环境,注意这里的"集成",是指将多个软件其中有 ...
- MindSpore!这款刚刚开源的深度学习框架我爱了!
[摘要] 本文主要通过两个实际应用案例:一是基于本地 Jupyter Notebook 的 MNIST 手写数据识别:二是基于华为云服务器的 CIFAR-10 图像分类,对开源框架 MindSpore ...
- 详解驱动开发中内核PE结构VA与FOA转换
摘要:本文将探索内核中解析PE文件的相关内容. 本文分享自华为云社区<驱动开发:内核PE结构VA与FOA转换>,作者: LyShark . 本章将探索内核中解析PE文件的相关内容,PE文件 ...
- 如何通过jstat命令进行查看堆内存使用情况?
摘要:jstat命令可以查看堆内存各部分的使用量,以及加载类的数量. 本文分享自华为云社区<JVM之通过jstat命令进行查看堆内存使用情况>,作者:共饮一杯无 . 基本概念 jstat是 ...
- 转角遇上Volcano,看HPC如何应用在气象行业
摘要:高性能计算(HPC)在各个领域都有广泛的应用.本文通过典型的HPC应用WRF,介绍了HPC应用在Kubernetes+Volcano上运行方式. Kubernetes已经成为云原生应用编排.管理 ...
- 我的程序跑了60多小时,就是为了让你看一眼JDK的BUG导致的内存泄漏。
这次的文章从JDK的J.U.C包下的ConcurrentLinkedQueue队列的一个BUG讲起.jetty框架里面的线程池用到了这个队列,导致了内存泄漏. 同时通过jconsole.VisualV ...
- Building wheel for opencv-python (pyproject.toml) ,安装命令增加 --verbose 参数
安装时间较长,通过 --verbose 参数 可以看在不在继续 Mac 安装 paddlehub 出现 Building wheels for collected packages: opencv-p ...
- 【Java爬虫】如何通过 API 递归分页爬取网页数据
前言 在最近的互联网项目开发中,需要获取用户的访问ip信息进行统计的需求,用户的访问方式可能会从微信内置浏览器.Windows浏览器等方式对产品进行访问. 当然,获取这些关于ip的信息是合法的.但是, ...
- 认证,权限,频率源码分析 自定义频率类 SimpleRateThrottle缓存频率类 基于APIView编写分页
目录 昨日回顾 三种位置的token获取 三种权限校验方式 原生django的cookie+session认证底层原理 断点调试使用 认证,权限,频率源码分析(了解) 权限源码分析 认证源码分析 频率 ...


