有木有看我上一篇博文 XA与两阶段提交?木有的赶紧先去看看先把,那是基础,最近也对其做了更新,自认为变得更logic及清晰了,看没看过都回去翻翻把~
上文提到 两阶段提交存在一个缺陷——若 某个回复了可提交的 资源管理器A 与 “其他一部分资源管理者B 及 协调者C" 失联 后,无法判定自身应该提交或者回滚,只能阻塞等待,完全失去了可用性。
三阶段提交协议的设计就是为了解决这个问题的。它同时兼顾了 强一致性 以及 可用性。但不同于两阶段提交,三阶段解决这个问题假设的模型中,是不存在网络断开但主机还存活着的这种情况,一旦失联,那么就是对方主机挂了。
其实这个就是CAP理论中,保留C以及A 不考虑P的情况(CAP理论可以看我的另外一篇博文——如何理解CAP)。
正因为它没有考虑断网的情况,以及需要三次来回的网络请求,耗时长 所以在现实世界中极少使用,仅仅只是供大家学习参考其 加入约定解决问题 的思想
三阶段提交是将两阶段提交中的第二阶段拆成了两部分 preCommit 以及 doCommit变成 一共三个阶段 以及为 这些不同的阶段加上一些约定来实现 一致性及可用性的,具体如下图:
之前在两阶段提交中已经论证过了,除了 【资源管理器A 与 “其他一部分资源管理者B 及 协调者C" 失联 后,无法判定自身应该提交或者回滚】 的情况外,都可保证一致性,因此在这不对其他情况作讨论,只分析这一种情况。
在变成三阶段提交后, A 与”协调者C及参与者B“失联(这里限定为B及C挂了)可分为两种情况:
A收到了preCommit的请求,A没有收到preCommit的请求。
一) A没有收到preCommit的请求
这时其他机器都挂了,根据约定,我就超时回滚啦。
但为什么回滚没有问题呢?这个时候其他主机虽然挂了,但是其必然处于没有提交的状态。理由如下:
1、A并没有回复ACK给协调者,协调者不可能发送提交命令给其他资源管理者
2、其他资源管理者B即使处于preCommit状态,也不会存在因为超时进行提交而A不知道的情况。因为超时提交前,B可以进行广播——我要进行超时提交啦,通知完所有机器后再执行提交!这个通知必然会告知正在运行的A。
当其他机器根据write-ahead-log恢复到本事务时,可以跟当前的正在运作的机器询问这一笔事务应该回滚或者提交,从而恢复到一致状态。(什么?这个时候只剩下你孤零零一个?好吧,你就只能阻塞等待了,这估计不是三阶段提交协议的讨论范围了....)
因此当A没有收到preCommit请求与其他机器失联进行回滚是可以保证一致性的。
二)A收到了preCommit的请求
这时其他机器都挂了,根据约定,A就执行提交操作了。
要执行COMMIT就要确定其他资源管理器都没有执行rollback操作,这个根据条件能推断出来么?
1、协调者有可能发送ROLLBACK指令么?
不可能。因为根据我们的设定。网络绝对畅通。只要发送过ROLLBACK指令,存活的A一定可以收到。(什么?发给其他资源管理者后,其他资源管理者执行回滚操作后 跟协调者一起挂了?好吧,这种情况也是可以破的....其他资源管理者回滚前再广播一次回滚请求即可...A这样就肯定能收到这个回滚请求了)
2、其他没有收到preCommit请求的机器会不会在挂了之前就达到超时限制,自行回滚了?
机器可以在回滚前向所有人,包括A。因此不存在 A没有收到回滚通知 而超时提交的情况。
当其他宕机机器根据write-ahead-log恢复到本事务时,可以跟当前的正在运作的机器询问这一笔事务应该回滚或者提交,从而恢复到一致状态。
综上,三阶段提交在 不考虑网络断开的情况下,解决了一致性及可用性的问题。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于