Mycat 分布式事务实现

Dcr 1年前 ⋅ 995 阅读

XA规范

  • 概念 X/Open组织(既现在的Open Group)定义了分布式事务处理模型.X/Open DTP模型包括应用程序(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操作。根据响应情况,有以下两种可能。

·假如协调者从所有参与者那里获得的反馈都是 Yes 响应,则执行事务。

·假如有任何一个参与者向协调者发送了 No 响应,或者等待超时之后协调者都没有接到参与者的响应,则执行事务的中断。

(3)DoCommit阶段:该阶段进行真正的事务提交,也可以分为执行提交、中断事务两种执行情况。

执行提交的过程如下。

·协调者接收到参与者发送的ACK响应后,将从预提交状态进入提交状态,并向所有参与者发送doCommit请求。

·事务提交参与者接收到doCommit请求之后,执行正式的事务提交,并在完成事务提交之后释放所有的事务资源。

·事务提交完之后,向协调者发送ACK响应。

·协调者接收到所有参与者的ACK响应之后,完成事务。中断事务的过程如下。

·协调者向所有参与者发送abort请求。

·参与者接收到 abort 请求之后,利用其在第 2 个阶段记录的 undo 信息来执行事务的回滚操作,并在完成回滚之后释放所有的事务资源。

·参与者完成事务回滚之后,向协调者发送 ACK 消息。

·协调者接收到参与者反馈的 ACK 消息之后,执行事务的中断。

  • MyCat 中分布式事务的实现

MyCat在1.6版本以后已经完全支持XA分布式强事务了,先通过一个简单的demo 来了解Mycat中XA的用法.

用户应用测(AP)的使用流程如下:

  1. set autocommit=0 在应用层需要设置事务不能自动提交;
  2. set xa=on 在SQL中设置XA为开启状态;
  3. 执行SQL insert into travelrecord(id,name) values(1,'N'),(6000000,'A'),(321,'D'),(13400000,'C'),(59,'E');
  4. commit 或者 rollback 对事务进行提交或者回滚.

1-1.png

Mycat 内部实现侧的实现流程如下:

(1)set autocommit=0

将 MysqlConnection 中的 autocommit 设置为 false;

(2)set xa=on

在Mycat中开启 XA 事务管理器,用 MycatServer.getInstance().genXATXID()生成 XID,用XA START XID 命令进行 XA 事务开始标记,继续拼装 SQL 业务(Mycat 会将上面的 insert 数据分片到不同的节点上),拼装 XA END XID,XA PREPARE XID 最后进行 1pc 提交并记录日志到 tm.log 中,如果 1pc 阶段有异常,则直接回滚事务 XA ROLLBACK xid。

(3)在多节点 MySQL 中全部进行 2pc 提交(XA COMMIT),提交成功后,事务结束;如果有异常,则对事务进行重新提交或者回滚。

Mycat 中的 XA 分布式事务的异常处理流程如下:

(1)一阶段 commit 异常:如果 1pc 提交任意一个 mysql 节点无法提交或者异常,则全部节点的事务进行回滚,抛出异常给应用侧事务回滚。

(2)Mycat Crash Recovery

Mycat 崩溃以后,根据 tm.log 事务日志再进行重启恢复,mycat 启动后执行事务日志查找

各个节点中已经 prepared 的 XA 事务,进行 commit 或者 rollback。

相关类说明

通过用户应用侧发送 set xa = on; SQL开启Mycat内部XA事务管理器的功能,事务管理器将对MySQL数据库进行XA方式的事务管理;

  • MySQLConnection:数据库连接。

  • NonBlockingSession:用户连接 Session。

  • MultiNodeCoordinator:协调者。

  • CommitNodeHandler:分片提交处理。

  • RollbackNodeHandler:分片回滚处理。

Mycat-Server github地址

全部评论: 0

    我有话说: