分布式事务专题之6、分布式事务解决方案之 3PC(三阶段提交)

目录

1. 回顾2PC

举个例子,A邀请B、C一起打王者荣耀,2PC过程如下:

A是协调者,B、C是参与者。

1.1. 阶段1(prepare阶段)

(1)、step1-1:A微信B

  1. step1-1-1A->B:有空么,我们约C一起王者荣耀
  2. step1-1-2B->A:有空
  3. step1-1-3A->B:那你现在就打开电脑,登录王者荣耀,你等着,我去通知C,然后开个房间
  4. step1-1-4B->A:已登录

(2)、step1-2:A微信C

  1. step1-2-1A->C:有空么,我约了B一起王者荣耀
  2. step1-2-2C->A:有空
  3. step1-2-3A->C:那你现在就打开电脑,登录王者荣耀,你等着,我去开个房间
  4. step1-2-4C->A:已登录

1.2. 阶段2(commit阶段)

此时B、C都已经登录王者容易了,然后A登录王者荣耀开了个房间

(1)、step2-1:A微信B

  1. step2-1-1A->B:房间号是xxx,你可以进来了
  2. step2-1-2B->A:我的,我进来了

(2)、step2-2:A微信C

  1. step2-2-1A->C:房间号是xxx,你可以进来了
  2. step2-2-2C->A:我的,我进来了

然后3个人开始爽歪歪了。

1.3. 2PC一些异常情况

(1)、情况1:step1-2-4超时,导致A无法收到C已登录的消息

此时A不知道C是什么情况,但是2PC中协调者这边有超时机制,如果协调者给参与者发送信息,长时间得不到回应时,将作为失败处理,此时A会给B和C发送rollback消息,让B和C都进行回滚,即取消游戏。

(2)、情况2:step1-1之后,协调者A挂了

此时B已经打开电脑在那等着了,却始终不见A、C的踪影,相当苦恼,也不知道还要等多久,苦逼!

(3)、情况3:阶段1之后,协调者A挂了

此时B、C登录账号了,也等了十几分钟了,就是不见A的踪影,也只能干等着,什么事情也做不了。

(4)、情况4:step2-2-1出现问题,C网络故障

此时C收不到A发送过来的消息,结果是导致A和B都已经进入房间了,就缺C了,游戏无法正常开始,导致最终的结果和期望的结果无法一致(期望3个人一起玩游戏,实际上房间里只有2个人)

1.4. 总的来说,2PC主要有2个问题

(1)、参与者干等的问题

参与者只能按照协调者的指令办事,当收不到协调者的指令的时候,参与者只能坐等,在db中的效果,操作的数据会被一直锁着,导致其他操作者被阻塞。

(2)、数据不一致的问题

commit阶段,协调者或者参与者挂掉,都可能导致最终数据不一致的问题。

2. 3PC

3PC主要解决了2PC中commit阶段参与者干等的问题,2PC中commit阶段,若协调者挂了,参与者不知道如何走了。2PC中只有协调者这边有超时机制,而3PC中,协调者和参与者这边引入了超时机制,commit阶段,若参与超过一定的时间收不到commit命令,参与者会自动提交,从而解决了2PC中资源长时间被锁的问题。

3PC相对于2PC,多了一个阶段,相当于把2PC的准备阶段再次一分为二,这样三阶段提交就有CanCommitPreCommitDoCommit三个阶段。

2.1. 阶段1:CanCommit阶段

之前2PC的一阶段是本地事务执行结束后,最后不Commit,等其它服务都执行结束并返回Yes,由协调者发出commit才真正执行commit,而这里的CanCommit指的是 尝试获取数据库锁 如果可以,就返回Yes。

这阶段主要分为2步

事务询问:协调者向参与者发送CanCommit请求。询问是否可以执行事务提交操作。然后开始等待参与的响应。

响应反馈:参与者接到CanCommit请求之后,正常情况下,如果其自身认为可以顺利执行事务,则返回Yes响应,并进入预备状态。否则反馈No,然后事务就结束了,此时参与者并没有执行任务任何操作。

2.2. 阶段2:PreCommit阶段

在阶段一中,如果所有的参与者都返回Yes的话,那么就会进入PreCommit阶段进行事务预提交。这里的PreCommit阶段 跟上面的第一阶段是差不多的,只不过这里 协调者和参与者都引入了超时机制(2PC中只有协调者可以超时,参与者没有超时机制)。

2.3. 阶段3:DoCommit阶段

这里跟2pc的阶段二是差不多的。

3. 案例:王者荣耀3PC过程

3.1. 正常的过程

(1)、阶段1(CanCommit阶段)

step1-1:A微信B
  1. step1-1-1A->B:有空么,我们约C一起王者荣耀
  2. step1-1-2B->A:有空
step1-2:A微信C
  1. step1-1-1A->B:有空么,我们约B一起王者荣耀
  2. step1-1-2B->A:有空

(2)、阶段2(PreCommit阶段)

step2-1:A微信B
  1. step2-1-1A->B:你现在就打开电脑,登录王者荣耀,等我消息,如果10分钟没消息,你就自己开个房间玩吧(参与者超时机制)。
  2. step2-1-2B->A:已登录
step2-2:A微信C
  1. step2-2-1A->C:那你现在就打开电脑,登录王者荣耀,等我消息,如果10分钟没消息,你就自己开个房间玩吧(参与者超时机制)。
  2. step2-2-2C->A:已登录

(3)、阶段3(DoCommit阶段)

此时B、C都已经登录王者容易了,然后A登录王者荣耀开了个房间

step3-1:A微信B
  1. step3-1-1A->B:房间号是xxx,你可以进来了
  2. step3-1-2B->A:我的,我进来了
step3-2:A微信C
  1. step3-2-1A->C:房间号是xxx,你可以进来了
  2. step3-2-2C->A:我的,我进来了

然后3个人开始爽歪歪了。

3.2. 异常的几种情况

(1)、阶段1异常

此时并没有进行事务操作,所以这个阶段出问题了,可以直接结束事务。

(2)、阶段2,参与者挂了

参与者挂了没关系,协调者直接通知其他参与者回滚。

(3)、阶段2,协调者挂了

协调者挂了,由于参与者引入了超时机制,所以参与者并不会无限期等待,等待一定的时间之后,会自动提交本地事务。

虽然这个超时机制解决了无限等待的问题,却并没有解决一致性的问题,比如上面3PC中step2-1:A微信B之后,协调者挂了,此时A已经登录了,但是C未收到A要求登录的消息,超时10分钟之后,A自己去开了一个游戏玩起来了,结果和期望的结果不一致了。

4. 3PC存在的问题

虽然解决了2PC中参与者长时间阻塞的问题(资源长时间无法释放的问题),但是并没有解决一致性的问题。

有没有办法解决这些问题?

有,TCC,接下来,我们来看TCC。

来源:http://www.itsoku.com/course/7/165
posted @ 2022-04-26 14:27  程序员小明1024  阅读(111)  评论(0编辑  收藏  举报