分布式一致性中,3PC如何解决了2PC无法保障的协调者和参与者都挂掉后,节点恢复后数据一致的问题?

论坛 期权论坛 期权     
wolfs niu   2018-9-22 00:57   1404   3

场景如下:协调者C,参与者A,B等节点。节点发生故障后,可能一直挂掉也可能恢复,所以其他节点要继续执行事务,当故障节点恢复后,如何保证所有参与者节点的一致性?
2PC下,
第一阶段,协调者C发送事务提议给A和B,A反馈no,B反馈yes
第二阶段,根据上一阶段反馈的信息,协调者C发送中止事务信息,当协调者C刚给A发送了事务中止信息后就挂掉了,A接收到中止信息,回滚时候后,也挂掉了。这时,新的协调者D,无法获知A的事务是提交了还是回滚了,这样B无论是提交事务还是回滚事务都有可能造成数据不一致。

3PC下,
第一阶段,协调者C发送canCommit给A和B,A和B都反馈yes
第二阶段,协调者C发送preCommit给A和B,A反馈不成功,B反馈成功
第三阶段,根据上一阶段反馈的信息,协调者C发送中止事务信息,当协调者C刚给A发送了事务中止信息后就挂掉了,A接收到中止信息,回滚时候后,也挂掉了。这时,新的协调者D,无法获知A的事务是提交了还是回滚了,这样B无论是提交事务还是回滚事务都有可能造成数据不一致。和2PC同样的问题,为什么网上都说3PC解决了这个问题,怎么解决的?不理解。

问题补充:

2PC做不到这点我理解,但是网上都在说3PC增加了preCommit阶段,解决了这个问题,现在还没明白3PC怎么解决了,还在查阅资料思考中。。。
关于网上对3PC如何解决这个问题的关键点就是所有存活的节点为preCommit状态的话,那故障节点就是可以提交的。
我不明白的地方就是,如果协调者C在第三阶段刚给A节点发送了abort还未给其他节点发送abort就挂掉了,A节点执行完回滚事务的操作后也挂掉了,现在其他存活的节点都是preCommit状态,新的协调者D进来后,查看存活的节点都是preCommit状体就让存活节点提交了事务,然后等故障节点A恢复后,A的事务是回滚的,数据就不一致了,不是和2PC一样没有解决问题么?


望知道的能解释下,谢谢!

分享到 :
0 人收藏

3 个回复

倒序浏览
2#
海绵宝宝  4级常客 | 2018-9-22 00:57:44 发帖IP地址来自

首先我觉得你的问题问的很棒,问的很多中文贴都有了站不住脚的地方。

我也是菜鸟,正在研究这一块,我觉得3pc主要解决了2pc的阻塞问题。而且相较2pc在一定程度上减少了数据不一致的可能,在一阶段投票通过后,二阶段存活节点都是preCommit的情况下,新协调者有理由相信事务可提交的概率比较大。当然这也会造成你说的数据不一致问题。这也是为什么需要其他去中心的算法来解决这个问题。

3#
Hollis  4级常客 | 2018-9-22 00:57:46 发帖IP地址来自

先来分析下参与者挂了,协调者也挂了的情况会有什么问题

这种情况比较复杂,我们分情况讨论。

  • 协调者和参与者在第一阶段挂了。
    • 由于这时还没有执行commit操作,新选出来的协调者可以询问各个参与者的情况,再决定是进行commit还是roolback。因为还没有commit,所以不会导致数据一致性问题。


  • 第二阶段协调者和参与者挂了,挂了的这个参与者在挂之前并没有接收到协调者的指令,或者接收到指令之后还没来的及做commit或者roolback操作。
    • 这种情况下,当新的协调者被选出来之后,他同样是询问所有的参与者的情况。只要有机器执行了abort(roolback)操作或者第一阶段返回的信息是No的话,那就直接执行roolback操作。如果没有人执行abort操作,但是有机器执行了commit操作,那么就直接执行commit操作。这样,当挂掉的参与者恢复之后,只要按照协调者的指示进行事务的commit还是roolback操作就可以了。因为挂掉的机器并没有做commit或者roolback操作,而没有挂掉的机器们和新的协调者又执行了同样的操作,那么这种情况不会导致数据不一致现象。


  • 第二阶段协调者和参与者挂了,挂了的这个参与者在挂之前已经执行了操作。但是由于他挂了,没有人知道他执行了什么操作。
    • 这种情况下,新的协调者被选出来之后,如果他想负起协调者的责任的话他就只能按照之前那种情况来执行commit或者roolback操作。这样新的协调者和所有没挂掉的参与者就保持了数据的一致性,我们假定他们执行了commit。但是,这个时候,那个挂掉的参与者恢复了怎么办,因为他之前已经执行完了之前的事务,如果他执行的是commit那还好,和其他的机器保持一致了,万一他执行的是roolback操作那?这不就导致数据的不一致性了么?虽然这个时候可以再通过手段让他和协调者通信,再想办法把数据搞成一致的,但是,这段时间内他的数据状态已经是不一致的了!


所以,2PC协议中,如果出现协调者和参与者都挂了的情况,有可能导致数据不一致。

为了解决这个问题,衍生除了3PC。我们接下来看看3PC是如何解决这个问题的。


再来看看3PC如何解决这个问题的

第二阶段协调者和参与者挂了,挂了的这个参与者在挂之前已经执行了操作。但是由于他挂了,没有人知道他执行了什么操作。

  • 这种情况下,当新的协调者被选出来之后,他同样是询问所有的参与者的情况来觉得是commit还是roolback。这看上去和二阶段提交一样啊?他是怎么解决一致性问题的呢?
  • 看上去和二阶段提交的那种数据不一致的情况的现象是一样的,但仔细分析所有参与者的状态的话就会发现其实并不一样。我们假设挂掉的那台参与者执行的操作是commit。那么其他没挂的操作者的状态应该是什么?他们的状态要么是prepare-commit要么是commit。因为3PC的第三阶段一旦有机器执行了commit,那必然第一阶段大家都是同意commit。所以,这时,新选举出来的协调者一旦发现未挂掉的参与者中有人处于commit状态或者是prepare-commit的话,那就执行commit操作。否则就执行rollback操作。这样挂掉的参与者恢复之后就能和其他机器保持数据一致性了。(为了简单的让大家理解,笔者这里简化了新选举出来的协调者执行操作的具体细节,真实情况比我描述的要复杂)

简单概括一下就是,如果挂掉的那台机器已经执行了commit,那么协调者可以从所有未挂掉的参与者的状态中分析出来,并执行commit。如果挂掉的那个参与者执行了rollback,那么协调者和其他的参与者执行的肯定也是rollback操作。

所以,再多引入一个阶段之后,3PC解决了2PC中存在的那种由于协调者和参与者同时挂掉有可能导致的数据一致性问题。


3PC存在的问题

在doCommit阶段,如果参与者无法及时接收到来自协调者的doCommit或者rebort请求时,会在等待超时之后,会继续进行事务的提交。

所以,由于网络原因,协调者发送的abort响应没有及时被参与者接收到,那么参与者在等待超时之后执行了commit操作。这样就和其他接到abort命令并执行回滚的参与者之间存在数据不一致的情况。

4#
匿名用户   | 2018-9-22 00:57:47 发帖IP地址来自
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:
帖子:
精华:
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP