Mycat分布式事务的实现分布式事务的实现
随着并发量、数据量越来越大及业务已经细化到不能再按照业务划分,我们不得不使用分布式数据库提高系统的性能。在分布
式系统中,各个节点在物理上都是相对独立的,每个节点上的数据操作都可以满足 ACID。但是,各独立节点之间无法知道其
他节点事务的执行情况,如果想让多台机器中的数据保存一致,就必须保证所有节点上的数据操作要么全部执行成功,要么全
部不执行,比较常规的解决方法是引入“协调者”来统一调度所有节点的执行。
XA 规范
X/Open 组织(即现在的 Open Group)定义了分布式事务处理模型。X/Open DTP 模型(1994)包括应用程序(AP)、事务
管理器(TM)、资源管理器(RM)、通信资源管理器(CRM)四部分。事务管理器(TM)是交易中间件,资源管理器
(RM)是数据库,通信资源管理器(CRM)是消息中间件。通常把一个数据库内部的事务处理看作本地事务,而分布式事务
处理的对象是全局事务。全局事务是指在分布式事务处理环境中,多个数据库可能需要共同完成一个工作,这个工作就是一个
全局事务。在一个事务中可能更新几个不同的数据库,此时一个数据库对自己内部所做操作的提交不仅需要本身的操作成功,
还需要全局事务相关的其他数据库的操作成功。如果任一数据库的任一操作失败,则参与此事务的所有数据库所做的所有操作
都必须回滚。XA就是X/Open DTP 定义的交易中间件与数据库之间的接口规范(即接口函数),交易中间件用它来通知数据
库事务的开始、结束、提交、回滚等,XA 接口函数由数据库厂商提供,根据这一思想衍生出二阶段提交协议和三阶段提交协
议。
二阶段提交
所谓的两个阶段是指准备阶段和提交阶段。
准备阶段指事务协调者(事务管理器)向每个参与者(资源管理器)发送准备消息,每个参与者要么直接返回失败消息(如权
限验证失败),要么在本地执行事务,写本地的 redo 和undo日志但不提交,可以进一步将准备阶段分为以下三步。
(1)协调者节点向所有参与者节点询问是否可以执行提交操作(vote),并开始等待各参与者节点的响应。
(2)参与者节点执行询问发起为止的所有事务操作,并将 undo 信息和 redo 信息写入日志。
(3)各参与者节点响应协调者节点发起的询问。如果参与者节点的事务操作实际执行成功,则它返回一个“同意”消息;如果
参与者节点的事务操作实际执行失败,则它返回一个“中止”消息。
提交阶段指如果协调者收到了参与者的失败消息或者超时,则直接向每个参与者发送回滚(Rollback)消息,否则发送提交
(Commit)消息,参与者根据协调者的指令执行提交或者回滚操作,释放所有事务在处理过程中使用的锁资源。
二阶段提交所存在的缺点如下。
(1)同步阻塞问题,在执行过程中所有参与节点都是事务阻塞型的,当参与者占用公共资源时,其他第三方节点访问公共资
源时不得不处于阻塞状态。
(2)单点故障,由于协调者的重要性,一旦协调者发生故障,则参与者会一直阻塞下去。
(3)数据不一致,在二阶段提交的第 2 个阶段中,当协调者向参与者发送 commit 请求之后发生了局部网络异常或者在发送
commit 请求的过程中协调者发生了故障,则会导致只有一部分参与者接收到了 commit 请求,而在这部分参与者在接收到
commit 请求之后就会执行commit操作,其他部分未接收到 commit 请求的机器则无法执行事务提交,于是整个分布式系统便
出现了数据不一致的现象。
由于二阶段提交存在诸如同步阻塞、单点问题、数据不一致、宕机等缺陷,所以,研究者们在二阶段提交的基础上做了改进,
提出了三阶段提交。
三阶段提交
三阶段提交(Three-phase commit,3PC),也叫作三阶段提交协议(Three-phase commitprotocol),是二阶段提交
(2PC)的改进版本。三阶段提交把二阶段提交的准备阶段再次一分为二,这样三阶段提交就有 CanCommit、PreCommit、
DoCommit 三个阶段。
(1)CanCommit 阶段:三阶段提交的 CanCommit 阶段其实和二阶段提交的准备阶段很像,协调者向参与者发送 commit 请
求,参与者如果可以提交就返回 Yes 响应,否则返回 No 响应。
(2)PreCommit 阶段:协调者根据参与者的反应情况来决定是否可以记录事务的 PreCommit操作。根据响应情况,有以下
两种可能。
1.假如协调者从所有参与者那里获得的反馈都是 Yes 响应,则执行事务。
2.假如有任何一个参与者向协调者发送了 No 响应,或者等待超时之后协调者都没有接到参与者的响应,则执行事务的中断。
(3)DoCommit阶段:该阶段进行真正的事务提交,也可以分为执行提交、中断事务两种执行情况。
执行提交的过程如下。