|NO.Z.00077|——————————|BigDataEnd|——|Hadoop&kafka.V62|——|kafka.v62|稳定性|一致性保证.v02|

一、HW和LEO正常更新案例
### --- HW和LEO正常更新案例

~~~     我们假设有一个topic,单分区,副本因子是2,即一个Leader副本和一个Follower副本。
~~~     我们看下当producer发送一条消息时broker端的副本到底会发生什么事情以及分区HW是如何被更新的。
### --- 初始状态

~~~     初始时Leader和Follower的HW和LEO都是0(严格来说源代码会初始化LEO为-1,
~~~     不过这不影响之后的讨论)。
~~~     Leader中的Remote LEO指的就是Leader端保存的Follower LEO,也被初始化成0。
~~~     此时,生产者没有发送任何消息给Leader,而Follower已经开始不断地给Leader发送FETCH请求了,
~~~     但因为没有数据因此什么都不会发生。值得一提的是,
~~~     Follower发送过来的FETCH请求因为无数据而暂时会被寄存到Leader端的purgatory(炼狱)中,
~~~     待500ms ( replica.fetch.wait.max.ms 参数)超时后会强制完成。
~~~     倘若在寄存期间生产者发来数据,则Kafka会自动唤醒该FETCH请求,让Leader继续处理。
### --- Follower发送FETCH请求在Leader处理完PRODUCE请求之后

~~~     producer给该topic分区发送了一条消息,此时的状态如下图所示:
### --- 如上图所示,Leader接收到PRODUCE请求主要做两件事情:

~~~     把消息写入Log,同时自动更新Leader自己的LEO
~~~     尝试更新Leader HW值。假设此时Follower尚未发送FETCH请求,
~~~     Leader端保存的RemoteLEO依然是0,因此Leader会比较它自己的LEO值和Remote LEO值,
~~~     发现最小值是0,与当前HW值相同,故不会更新分区HW值(仍为0)
~~~     PRODUCE请求处理完成后各值如下,Leader端的HW值依然是0,而LEO是1,Remote LEO也是0。
属性 阶段 旧值 新值 备注
Leader LEO PRODUCE处理完成 0 1 写入了一条数据
RemoteLEO PRODUCE处理完成 0 0 还未Fetch
LeaderHW PRODUCE处理完成 0 0 min(LeaderLEO=1,RemoteLEO=0)=0
FollowerLEO PRODUCE处理完成 0 0 还未Fetch
Follower HW PRODUCE处理完成 0 0 min(LeaderHW=0,FollowerLEO=0)=0
~~~     # 假设此时follower发送了FETCH请求,则状态变更如下:
~~~     # 本例中当follower发送FETCH请求时,Leader端的处理依次是:

~~~     读取Log数据
~~~     更新remote LEO = 0(为什么是0? 因为此时Follower还没有写入这条消息。
~~~     Leader如何确认Follower还未写入呢?这是通过Follower发来的FETCH请求中的Fetch offset来确定的)
~~~     尝试更新分区HW:此时Leader LEO = 1,Remote LEO = 0~~~     故分区HW值= min(LeaderLEO, Follower Remote LEO) = 0
~~~     把数据和当前分区HW值(依然是0)发送给Follower副本
~~~     # 而Follower副本接收到FETCH Response后依次执行下列操作:
~~~     写入本地Log,同时更新Follower自己管理的 LEO为1
~~~     更新Follower HW:比较本地LEO和 FETCH Response 中的当前Leader HW值,
~~~     取较小者,Follower HW = 0
~~~     # 此时,第一轮FETCH RPC结束,
~~~     # 我们会发现虽然Leader和Follower都已经在Log中保存了这条消息,但分区HW值尚未被更新,仍为0。
属性 阶段 旧值 新值 备注
LeaderLEO PRODUCE和Follower FETCH 处理完成 0 1 写入一条数据
RemoteLEO PRODUCE和Follower FETCH 处理完成 0 0 第一次fetch中offset为0
LeaderHW PRODUCE和Follower FETCH 处理完成 0 0
min(LeaderLEO=1,
RemoteLEO=0)=0
FollowerLEO PRODUCE和Follower FETCH 处理完成 0 1 同步了一条数据
FollowerHW PRODUCE和Follower FETCH 处理完成 0 0
min(LeaderHW=0,
FollowerLEO=1)=0
### --- Follower第二轮FETCH

~~~     分区HW是在第二轮FETCH RPC中被更新的,如下图所示:
### --- Follower发来了第二轮FETCH请求,Leader端接收到后仍然会依次执行下列操作:

~~~     # 读取Log数据
~~~     更新Remote LEO = 1(这次为什么是1了? 因为这轮FETCH RPC携带的fetch offset1~~~     那么为什么这轮携带的就是1了呢,因为上一轮结束后Follower LEO被更新为1了)
~~~     尝试更新分区HW:此时leader LEO = 1,Remote LEO = 1~~~     故分区HW值= min(Leader LEO,Follower Remote LEO) = 1~~~     把数据(实际上没有数据)和当前分区HW值(已更新为1)发送给Follower副本作为Response
~~~     # 同样地,Follower副本接收到FETCH response后依次执行下列操作:
~~~     写入本地Log,当然没东西可写,Follower LEO也不会变化,依然是1。
~~~     更新Follower HW:比较本地LEO和当前LeaderHW取小者。由于都是1,故更新follower HW= 1 。

~~~     # 此时消息已经成功地被复制到Leader和Follower的Log中且分区HW是1,
~~~     表明消费者能够消费offset = 0的消息。
属性 阶段 旧值 新值 备注
LeaderLEO PRODUCE和Follower FETCH 处理完成 1 1 未写入新数据
RemoteLEO PRODUCE和Follower FETCH 处理完成 0 1 第2次fetch中offset为1
LeaderHW PRODUCE和Follower FETCH 处理完成 0 1 min(RemoteLEO,LeaderLEO)=1
FollowerLEO PRODUCE和Follower FETCH 处理完成 1 1 未写入新数据
FollowerHW PRODUCE和Follower FETCH 处理完成 0 1
第2次fetch resp中的LeaderHW和本地FollowerLEO都是1
### --- FETCH请求保存在purgatory中,PRODUCE请求到来。

~~~     当Leader无法立即满足FECTH返回要求的时候(比如没有数据),
~~~     那么该FETCH请求被暂存到Leader端的purgatory中(炼狱),待时机成熟尝试再次处理。
~~~     Kafka不会无限期缓存,默认有个超时时间(500ms),一旦超时时间已过,则这个请求会被强制完成。
~~~     当寄存期间还没超时,生产者发送PRODUCE请求从而使之满足了条件以致被唤醒。
~~~     # 此时,Leader端处理流程如下:

~~~     Leader写Log(自动更新Leader LEO)
~~~     尝试唤醒在purgatory中寄存的FETCH请求
~~~     尝试更新分区HW

 
 
 
 
 
 
 
 
 

Walter Savage Landor:strove with none,for none was worth my strife.Nature I loved and, next to Nature, Art:I warm'd both hands before the fire of life.It sinks, and I am ready to depart
                                                                                                                                                   ——W.S.Landor

 

posted on   yanqi_vip  阅读(19)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示