在分布式数据库中,为保证分布式事务的原子性,需要在事务提交阶段提供一个原子提交算法。经典的算法包括两阶段提交阶段(Two-Phase Commit)、基于两阶段提交的改进算法–三阶段提交算法和基于Pasox的提交(非阻塞式提交协议)。每种提交算法不仅解决提交相关的问题外,还考虑在各种故障/环境情况下的恢复处理机制。接下来一起学习上述各种提交算法的原理及优缺点。
两阶段提交(2PC)是将提交操作分为两个部分,每个部分是一个阶段,也因此成为两阶段。
两阶段提交是指事务结束前,把在分布式事务中的事务进行提交的动作分解位两个阶段,每个阶段因分布式环境不同而执行不同的任务。第一个任务是投票任务,是完成这个任务的过程,该阶段称为准备阶段;第二个任务是执行投票结果,是完成这个任务的阶段,该阶段成为提交阶段。准备阶段是分布式环境中各个参与节点就事务提交或者回滚达成一致意见,然后进入提交阶段以实现事务的最终的状态。这样做的目的是为了保证事务ACID特性(后续内容会进一步进行阐述)中的原子性,即A。确切地说是保证分布式事务结束时提交阶段的原子性操作。两阶段提交算法中引入参与者和协调者:
准备阶段是2PC的第一阶段,其具体过程如下:
1)协调者节点在本地记录begin commit 记录信息到REDO日志;
2)协调者节点项所有的参与者询问是否可以执行提交操作(发起投票,准备消息),并开始等待所有参与者的响应;
3)参与者节点检查本地的子事务是否可以提交或者执行各自的子事务操作直到提交前一刻(注意:子事务已经被实际执行,使用封锁协议则参与者施加了锁导致其他并发事务会在在此阶段封锁被阻塞),此后参与者即可知道本地的子事务是否可以提交,如果可以,则将ready信息写入本地的REDO日志。
4)所有参与者向协调者发送相应信息。
- 如果参与者节点的子事务操作执行成功,则返回一个投票提交的消息,进入就绪状态等待协调者的进一步通知;
- 如果参与者节点的子事务操作执行失败,则将abort消息写入日志,然后回滚本地的子事务,并返回一个投票结束的消息给协调者。
提交阶段是2PC 的第二阶段,其具体过程如下:
case1:协调者从所有的参与者节点收到的消息均为“投票成功”的情况
1)协调者节点在本地记录commit信息到REDO日志;
2)协调者向所有的参与者节点发送Global-commit消息后,进入COMMIT状态;
3)参与者在收到Global-commit消息后,会在本地记录commit信息到REDO日志,正式完成提交操作(设置事务提交完成标志),并释放在整个事务期间所占用的资源;如果各个参与者使用了封锁并发访问控制机制,则必须在事务完成后释放锁资源;
4)参与者节点香协调者发送commit结束消息;
5)协调者收到所有参与者节点反馈的commit结束信后,完成事务,最后在本地记录end_commit信息到REDO日志。
case2:任意参与者节点在第一阶段返回的消息为“中止”,或者协调者节点在第一阶段的询问超时导致无法获取部分参与者节点的回应消息的情况
1)协调者在本地记录abort信息到REDO日志;
2)协调者向所有的参与者节点发出Global-abort消息,进入事务撤销/中止(abort)状态;
3)参与者节点收到协调者发出的Global-abort消息,记录abort消息至REDO日志中,利用事务的回滚机制执行回滚操作,并释放在整个事务期间所占用的资源。如果各个参与者使用了封锁并发访问控制机制,则必须在事务完成后释放锁资源;
4)参与者节点向协调者发送abort结束消息;
5)协调者收到所有参与者的abort结束消息后,完成事务,并在本地记录end_abort消息到REDO日志。
为了提高2PC的性能,出现了很多2PC的变形版本。其中,1PC表示一个事务只涉及一个节点,基本本地事务。当2PC蜕化为1PC时,不用考虑分布式事务在提交阶段可能遇到的问题,其本质就是一个单节点的单机事务,所以事务在本地直接被执行,然后提交或者回滚即可。
Tree 2PC协议、Dynamic two-phase commit (D2PC)也是队2PC协议的改进。前者将协调者和参与者组织为一棵树的形式,参与者作为节点可以向上层的其他参与者节点或者协调节点发送中止消息,上层节点有义务即刻向上传播中止消息直到协调节点。后者是前者的改进,没有预先确定的协调者,而是通过竞争选出昔协调者,且所有实例中因协调者因选举而可以不集中在一个固定节点上,降低了事务集中在一个节点上成为瓶颈的可能。
两阶段提交协议的优点:2PC原理简单,实现方便。目前绝大多数关系型数据库都是采用两阶段提交协议来实现分布式事务提交。
两阶段提交协议的缺点:
由于2PC存在同步阻塞、单点问题、脑裂等问题,因在有相关工作人员提出三阶段提交、基于Paxos协议的2PC等改进协议克服上述问题。
三阶段提交协议(three-Phase Commit,3PC)是对2PC的改进,改进之处在于:为协调者和参与者引入超时机制,并将2阶段的第一阶段细分为2个步骤,如此变成3阶段,即:“先询问是否可以提交,然后再所资源,最后真正提交”这三步。
如下图,3PC分为:canCommit、preCommit和 doCommit。
3PC引入超时提交的依据:
基于概率来决定的,当进入第三阶段时,参与者在第二阶段已经收到了PreCommit请求,那么协调者产生PreCommit请求的前提条件是他在第二阶段开始之前,收到所有参与者的CanCommit响应都是Yes。(一旦参与者收到了PreCommit,意味他知道大家其实都同意修改了)所以,一句话概括就是,当进入第三阶段时,由于网络超时等原因,虽然参与者没有收到commit或者abort响应,但是他有理由相信:成功提交的几率很大。
三阶段提交协议的优点: 相对于二级段提交协议,三阶段提交协议的最大的优点就是降低了参与者的阻塞的范围,并且能够在出现单点故障后继续达成一致
三阶段提交协议的缺点:
1)无故障修复:不能在发生分区的情况下进行故障修复。在分布式事务处理过程中,采用2PC或3PC机制时,因其分布式架构的特点,在事务提交算法中需要考虑分区发生的情况,以实现故障情况下下的恢复机制。
2)耗时长:3PC至少需要3次网络通信交互才能完成整个过程,这使得每个事务耗时边长。
3)数据不一致:如果进入preCommit 后,协调者发出的是中止请求,假设只有一个参与者收到并进行中止操作,则其他对于系统状态未知的参与者会根据3PC选择继续提交,此时系统会出现数据不一致现象。