分布式事务专题之6、分布式事务解决方案之 3PC(三阶段提交)
目录
1. 回顾2PC
举个例子,A邀请B、C一起打王者荣耀,2PC过程如下:
A是协调者,B、C是参与者。
1.1. 阶段1(prepare阶段)
(1)、step1-1:A微信B
step1-1-1:A->B:有空么,我们约C一起王者荣耀
step1-1-2:B->A:有空
step1-1-3:A->B:那你现在就打开电脑,登录王者荣耀,你等着,我去通知C,然后开个房间
step1-1-4:B->A:已登录
(2)、step1-2:A微信C
step1-2-1:A->C:有空么,我约了B一起王者荣耀
step1-2-2:C->A:有空
step1-2-3:A->C:那你现在就打开电脑,登录王者荣耀,你等着,我去开个房间
step1-2-4:C->A:已登录
1.2. 阶段2(commit阶段)
此时B、C都已经登录王者容易了,然后A登录王者荣耀开了个房间
(1)、step2-1:A微信B
step2-1-1:A->B:房间号是xxx,你可以进来了
step2-1-2:B->A:我的,我进来了
(2)、step2-2:A微信C
step2-2-1:A->C:房间号是xxx,你可以进来了
step2-2-2:C->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的准备阶段再次一分为二,这样三阶段提交就有CanCommit
、PreCommit
、DoCommit
三个阶段。
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
step1-1-1:A->B:有空么,我们约C一起王者荣耀
step1-1-2:B->A:有空
step1-2:A微信C
step1-1-1:A->B:有空么,我们约B一起王者荣耀
step1-1-2:B->A:有空
(2)、阶段2(PreCommit阶段)
step2-1:A微信B
step2-1-1:A->B:你现在就打开电脑,登录王者荣耀,等我消息,如果10分钟没消息,你就自己开个房间玩吧(参与者超时机制)。
step2-1-2:B->A:已登录
step2-2:A微信C
step2-2-1:A->C:那你现在就打开电脑,登录王者荣耀,等我消息,如果10分钟没消息,你就自己开个房间玩吧(参与者超时机制)。
step2-2-2:C->A:已登录
(3)、阶段3(DoCommit阶段)
此时B、C都已经登录王者容易了,然后A登录王者荣耀开了个房间
step3-1:A微信B
step3-1-1:A->B:房间号是xxx,你可以进来了
step3-1-2:B->A:我的,我进来了
step3-2:A微信C
step3-2-1:A->C:房间号是xxx,你可以进来了
step3-2-2:C->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