分布式事务与 Seata 初探

Posted by MatthewHan on 2020-12-10

分布式事务

布式事务的实现有很多种,最具有代表性的是由Oracle Tuxedo系统提出的XA分布式事务协议。

XA协议包含**两阶段提交(2PC)三阶段提交(3PC)**两种实现。

当然该协议主要是一种理论方式,具体落地有相应的组件(Seata等)或者代码中自行实现。

二段式提交

当队员收到就位确认提示后,如果已经就位,就选择“是”,如果还没就位,就选择“否”。

相应的,在队长发起就位确认的时候,有可能某些队员还并没有就位。

那么XA协议究竟是什么样子呢?在XA协议中包含着两个角色:事务协调者事务参与者

成功的流程

让我们来看一看他们之间的交互流程:

在XA分布式事务的第一阶段,作为事务协调者的节点会首先向所有的参与者节点发送Prepare请求。

在接到Prepare请求之后,每一个参与者节点会各自执行与事务有关的数据更新,写入Undo Log和Redo Log。如果参与者执行成功,暂时不提交事务,而是向事务协调节点返回“完成”消息。

当事务协调者接到了所有参与者的返回消息,整个分布式事务将会进入第二阶段。

在XA分布式事务的第二阶段,如果事务协调节点在之前所收到都是正向返回,那么它将会向所有事务参与者发出Commit请求。

接到Commit请求之后,事务参与者节点会各自进行本地的事务提交,并释放锁资源。当本地事务完成提交后,将会向事务协调者返回“完成”消息。

当事务协调者接收到所有事务参与者的“完成”反馈,整个分布式事务完成。

失败的流程

在XA的第一阶段,如果某个事务参与者反馈失败消息,说明该节点的本地事务执行不成功,必须回滚。

于是在第二阶段,事务协调节点向所有的事务参与者发送Abort请求。接收到Abort请求之后,各个事务参与者节点需要在本地进行事务的回滚操作,回滚操作依照Undo Log来进行。

以上就是XA两阶段提交协议的详细过程。

细节

首先 2PC 是一个同步阻塞协议,像第一阶段协调者会等待所有参与者响应才会进行下一步操作,当然第一阶段的协调者有超时机制,假设因为网络原因没有收到某参与者的响应或某参与者挂了,那么超时后就会判断事务失败,向所有参与者发送回滚命令。

二段式提交的不足

  1. 性能问题

XA协议遵循强一致性。在事务执行过程中,各个节点占用着数据库资源,只有当所有节点准备完毕,事务协调者才会通知提交,参与者提交后释放资源。这样的过程有着非常明显的性能问题。

  1. 协调者单点故障问题

事务协调者是整个XA模型的核心,一旦事务协调者节点挂掉,参与者收不到提交或是回滚通知,参与者会一直处于中间状态无法完成事务。(参与者不具备超时机制)

  1. 丢失消息导致的不一致问题。

在XA协议的第二个阶段,如果发生局部网络问题,一部分事务参与者收到了提交消息,另一部分事务参与者没收到提交消息,那么就导致了节点之间数据的不一致。

三段式提交

  1. XA三阶段提交

XA三阶段提交在两阶段提交的基础上增加了CanCommit阶段,并且引入了超时机制。一旦事物参与者迟迟没有接到协调者的commit请求,会自动进行本地commit。这样有效解决了协调者单点故障的问题。但是性能问题和不一致的问题仍然没有根本解决。

  1. TCC事务

TCC事务是Try - Confirm - Cancel三种指令的缩写,其逻辑模式类似于XA两阶段提交,但是实现方式是在代码层面来人为实现。

其实从思想上看和 2PC 差不多,都是先试探性的执行,如果都可以那就真正的执行,如果不行就回滚。

比如说一个事务要执行A、B、C三个操作,那么先对三个操作执行预留动作。如果都预留成功了那么就执行确认操作,如果有一个预留失败那就都执行撤销动作。

TCC 对业务代码的侵入较大,开发量也比较大但是提供了较好的性能。

XA 和 TCC 的区别

XA 是一整个长事务,对数据库进行加锁,所以性能拉胯而且会有长事务风险。但是 TCC 是几个小事务(本地事务),最终一致性,不会出现长事务的锁风险,保证分布式性能。

在 Seata 中如需改造成 TCC 模式,需要加上核心注解@LocalTCC,并写三个接口,分别对应 Try - Confirm - Cancel,如saveOrder()commit()rollbackTcc()方法。代码量确实会大一些,并且后期维护加重。

  1. MQ事务

利用消息中间件来异步完成事务的后一半更新,实现系统的最终一致性。这个方式避免了像XA协议那样的性能问题。

Seata

TC:seata 服务端

TM:@GlobalTransactional注解的方法,事务的发起方

RM:一个数据库就是 RM,事务的参与方

TM 开启分布式事务,TM 向 TC 注册全局事务记录

业务场景,编排数据库,服务等事务内资源,RM 向 TC 报备资源准备状态

TM 结束分布式事务,事务一阶段结束(TM 通知 TC 提交或回滚分布式事务)

TC 汇总事务信息,决定分布式事务是提交还是回滚

TC 通知所有 RM 提交或回滚资源,事务二阶段结束