分布式事务
布式事务的实现有很多种,最具有代表性的是由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 是一个同步阻塞协议,像第一阶段协调者会等待所有参与者响应才会进行下一步操作,当然第一阶段的协调者有超时机制,假设因为网络原因没有收到某参与者的响应或某参与者挂了,那么超时后就会判断事务失败,向所有参与者发送回滚命令。
二段式提交的不足
- 性能问题
XA协议遵循强一致性。在事务执行过程中,各个节点占用着数据库资源,只有当所有节点准备完毕,事务协调者才会通知提交,参与者提交后释放资源。这样的过程有着非常明显的性能问题。
- 协调者单点故障问题
事务协调者是整个XA模型的核心,一旦事务协调者节点挂掉,参与者收不到提交或是回滚通知,参与者会一直处于中间状态无法完成事务。(参与者不具备超时机制)
- 丢失消息导致的不一致问题。
在XA协议的第二个阶段,如果发生局部网络问题,一部分事务参与者收到了提交消息,另一部分事务参与者没收到提交消息,那么就导致了节点之间数据的不一致。
三段式提交
- MQ事务
利用消息中间件来异步完成事务的后一半更新,实现系统的最终一致性。这个方式避免了像XA协议那样的性能问题。
- XA三阶段提交
XA三阶段提交在两阶段提交的基础上增加了CanCommit阶段,并且引入了超时机制。一旦事物参与者迟迟没有接到协调者的commit请求,会自动进行本地commit。这样有效解决了协调者单点故障的问题。但是性能问题和不一致的问题仍然没有根本解决。
- TCC事务
TCC事务是Try - Confirm - Cancel三种指令的缩写,其逻辑模式类似于XA两阶段提交,但是实现方式是在代码层面来人为实现。
其实从思想上看和 2PC 差不多,都是先试探性的执行,如果都可以那就真正的执行,如果不行就回滚。
比如说一个事务要执行A、B、C三个操作,那么先对三个操作执行预留动作。如果都预留成功了那么就执行确认操作,如果有一个预留失败那就都执行撤销动作。
TCC 对业务代码的侵入较大,开发量也比较大但是提供了较好的性能。
XA 和 TCC 的区别
XA 是一整个长事务,对数据库进行加锁,所以性能拉胯而且会有长事务风险。但是 TCC 是几个小事务(本地事务),最终一致性,不会出现长事务的锁风险,保证分布式性能。
在 Seata 中如需改造成 TCC 模式,需要加上核心注解@LocalTCC
,并写三个接口,分别对应 Try - Confirm - Cancel,如saveOrder()
、commit()
、rollbackTcc()
方法。代码量确实会大一些,并且后期维护加重。
Seata
TC:seata 服务端
TM:@GlobalTransactional
注解的方法,事务的发起方
RM:一个数据库就是 RM,事务的参与方
TM 开启分布式事务,TM 向 TC 注册全局事务记录
业务场景,编排数据库,服务等事务内资源,RM 向 TC 报备资源准备状态
TM 结束分布式事务,事务一阶段结束(TM 通知 TC 提交或回滚分布式事务)
TC 汇总事务信息,决定分布式事务是提交还是回滚
TC 通知所有 RM 提交或回滚资源,事务二阶段结束