两阶段提交协议是很常见的解决分布式事务的方式,他可以保证分布式事务中,要么所有参与的进程都提交事务成功,要么都取消事务,这样做可以在分布式环境中保持ACID中A(原子性)。
在两阶段提交协议中,包含了两种角色:协调者与参与者。参与者就是实际处理事务的机器,而协调者就是其中一台单独的处理分布式事务的机器。
该算法分为两个阶段:
1.投票阶段
2.提交阶段
阶段1:请求阶段(commit-requestphase,或称表决阶段,votingphase)
在请求阶段,协调者将通知事务参与者准备提交或取消事务,然后进入表决过程。在表决过程中,参与者将告知协调者自己的决策:同意(事务参与者本地作业执行成功)或取消(本地作业执行故障)。这里的取消是指该参与者所在的机器没有准备好,或者出现了故障。因此无法执行该事务。
阶段2:提交阶段(commitphase)
在该阶段,协调者将基于第一个阶段的投票结果进行决策:提交或取消。当且仅当所有的参与者同意提交事务协调者才通知所有的参与者提交事务,否则协调者将通知所有的参与者取消事务。参与者在接收到协调者发来的消息后将执行响应的操作。协调者如果发现有一个投票是VOTE_ABORT,那么将创建一个GLOBAL_ABORT通知所有的参与者终止该事务。如果都是VOTE_COMMIT,那么协调者将发送一个GLOBAL_COMMIT,告知所有的参与者执行该事务。
图1,图2 是协调者与参与者的运行时的状态机。
图1 协调者的状态机
图2 参与者的状态机
实现中的问题:
当然如果协调者发送一个GLOBAL_COMMIT信息,A收到了,B没收到,B可以根据A的状态,自动将自己设置成COMMIT状态。同理可以根据其他的参与者的状态设置自己的状态为GLOBAL_ABORT状态。
但是如果Q发现其他的节点都是处于READY状态,并很长时间都没有变化,说明协调者服务器down机了,这也就是该算法可能会出现的问题,协调者的长时阻塞问题。解决该问题的方法就是设置超时机制,当时间超过了最长等待时间,设置该事务为ABORT状态。