分布式事务
分布式事务
分布式事务用于在分布式系统中保证不同节点之间的数据一致性。分布式事务的实现有很多种,最具有代表性的是由Oracle Tuxedo系统提出的XA分布式事务协议。
一、XA事务
1、什么是XA?
XA是由X/Open组织提出的分布式事务的规范。 XA规范主要定义了(全局)事务管理器(TM)和(局 部)资源管理器(RM)之间的接口。主流的关系型数据库产品都是实现了XA接口的。
2、XA事务的组成
XA事务由一个或多个资源管理器、一个事务管理器以及一个应用程序组成。
资源管理器(Resource Managers):提供访问事务资源的方法。通常一个数据库就是一个资源管理器。
事务管理器(Transaction Manager):协调参与全局事务中的各个事务。需要和参与全局事务的所有资源管理器进行通信。
应用程序(Application Program):定义事务的边界,指定全局事务中的操作。
XA协议包含两阶段提交(2PC)和三阶段提交(3PC)两种实现,后面重点介绍两阶段提交的具体过程。
二、两阶段提交(two-phase commit)
1、两阶段提交的实现过程
第一阶段为准备(prepare)阶段。
所有参与全局事务的节点都开始准备(PREPARE)并锁住需要的资源,告诉事务管理器它们准备好提交了。
2、第二阶段为提交阶段(commit)。
事务管理器告诉资源管理器执行ROLLBACK还是COMMIT。如果任何一个节点显示不能提交,则所有的节点都被告知需要回滚。可见与本地事务不同的是,分布式事务需要多一次的PREPARE操作,待收到所有节点的同意信息后,再进行COMMIT或者ROLLBACK操作。
3、XA两阶段提交成功情况的处理流程
第一阶段(prepare phase):
1)作为事务协调者的节点会首先向所有的参与者节点发送Prepare请求。
2)在接到Prepare请求之后,每一个参与者节点会各自执行与事务有关的数据更新,写入Undo Log和Redo Log。如果参与者执行成功,暂时不提交事务,而是向事务协调节点返回“完成”消息。
3)当事务协调者接收到了所有参与者的返回消息,整个分布式事务将会进入第二阶段。
第二阶段(commit phase):
如果事务协调节点在之前所收到都是正向返回,那么它将会向所有事务参与者发出Commit请求。接到Commit请求之后,事务参与者节点会各自进行本地的事务提交,并释放锁资源。当本地事务完成提交后,将会向事务协调者返回“完成”消息。并释放事务处理过程中使用的锁资源。
当事务协调者接收到所有事务参与者的“完成”反馈,整个分布式事务完成。
4、XA两阶段提交失败情况的处理流程
第一阶段
如果某个事务参与者反馈失败消息,说明该节点的本地事务执行不成功,必须回滚。
第二阶段
事务协调节点向所有的事务参与者发送Abort请求。接收到Abort请求之后,各个事务参与者节点需要在本地进行事务的回滚操作,回滚操作依照Undo Log来进行。并释放事务处理过程中使用的锁资源。
5、XA两阶段提交的不足
1) 性能问题
XA协议遵循强一致性。在事务执行过程中,各个节点占用着数据库资源,只有当所有节点准备完毕,事务协调者才会通知提交,参与者提交后释放资源。也就是说,资源的锁定需要持续到第二阶段实际的提交或者回滚操作。这样的过程有着非常明显的性能问题。
2)协调者单点故障问题
事务协调者是整个XA模型的核心,一旦事务协调者节点挂掉,参与者收不到提交或是回滚通知,参与者会一直处于中间状态无法完成事务。
3)丢失消息导致的不一致问题。
在XA协议的第二个阶段,如果发生局部网络问题,一部分事务参与者收到了提交消息,另一部分事务参与者没收到提交消息,那么就导致了节点之间数据的不一致。
总的来说,XA性能局限性在于效率低下,准备阶段的成本持久,全局事务状态的成本持久,性能与本地事务相差10倍左右;提交前,出现故障难以恢复和隔离问题。
三、其它分布式事务方案
如何避免XA两阶段提交的种种问题呢?实际上有许多其他的分布式事务方案可供选择:
1. 三阶段提交(three-phase commit)
在两阶段提交中,第一个阶段是询问所有参与者是否可以提交事务。在 XA 三阶段提交中,这一阶段被拆分成 CanCommit 阶段和 PreCommit 阶段。
1)CanCommit 阶段
协调者向所有参与者发送 CanCommit 消息,询问它们是否可以提交事务。参与者在收到 CanCommit 消息后,会执行一些检查,确保自己的事务可以提交。如果检查通过,参与者会回复 "Yes",表示可以提交;否则,回复 "No",表示不能提交。
- 如果在 CanCommit 阶段协调者没有在规定的时间内收到所有参与者的反馈,协调者会启动超时处理。
- 协调者可以根据具体的实现,在超时后执行不同的动作,例如中断事务、选择性地中断一部分事务等。
2)PreCommit 阶段
如果 CanCommit 阶段的所有参与者都回复 "Yes",那么协调者向所有参与者发送 PreCommit 消息,告诉它们准备好提交事务。参与者在收到 PreCommit 消息后,会在本地执行事务的预提交操作,但不会真正提交。预提交操作可能包括写日志、锁定资源等。
- 如果在 PreCommit 阶段发生了超时,协调者可能会认为参与者无法正常提交事务,因此协调者会发送中断事务的请求。
- 参与者在收到中断请求后,需要进行相应的回滚操作。
3)DoCommit 阶段和DoAbort 阶段
如果在 PreCommit 阶段没有发生错误,协调者向所有参与者发送 DoCommit 消息,表示可以最终提交事务。
如果在 CanCommit 或 PreCommit 阶段的任何时候有参与者回复 "No",或者在规定时间内没有收到某个参与者的回复,协调者会发送 DoAbort 消息,表示事务中止。
参与者在收到 DoCommit 或 DoAbort 消息后,根据消息执行最终的提交或回滚操作。
分析:XA三阶段提交在两阶段提交的基础上增加了CanCommit阶段,并且引入了超时机制。一旦事务参与者迟迟没有接到协调者的commit请求,会自动进行本地commit。这样有效解决了协调者单点故障的问题。但是性能问题和不一致的问题仍然没有根本解决。
2. MQ事务
本地消息表/可靠消息最终一致性。利用消息中间件来异步完成事务的后一半更新,实现系统的最终一致性。这个方式避免了像XA协议那样的性能问题。
举个栗子:
跨行转账可通过本地消息表来实现。
用户 A 向用户 B 发起转账,首先系统会扣掉用户 A 账户中的金额,将该转账消息写入消息表中,如果事务执行失败则转账失败,如果转账成功,系统中会有定时轮询消息表,往 mq 中写入转账消息,失败重试。mq 消息会被实时消费并往用户 B 中账户增加转账金额,执行失败会不断重试。
商城用户订单数据状态变更,会将变更状态记录消息表中,脚本将订单状态消息写入 mq,最终消费 mq 给用户发送邮件、短信、push 等。
3. TCC事务
TCC事务是Try、Commit、Cancel三种指令的缩写,其逻辑模式类似于XA两阶段提交,但是实现方式是在代码层面来人为实现。
1)Try 阶段
每个参与者执行一些预备工作,如资源的保留等,但不做实际的业务处理。
2)Confirm 阶段
所有参与者都执行正式的业务操作,将资源的状态正式提交,通常是数据的持久化。
3)Cancel 阶段
如果事务执行过程中出现了问题,或者某些参与者不能完成 Confirm 阶段,就会调用 Cancel 阶段来回滚操作,撤销 Try 阶段的操作。
在 Cancel 阶段,每个参与者应该撤销 Try 阶段的操作,也就是执行取消的操作,以保证数据的一致性。如果 Cancel 操作失败,会产生一定的风险,可能导致数据不一致或资源未能正确释放。
Cancel失败的处理策略:重试机制、补偿机制(确保系统最终达到一致性)
PS:目前已经有比较成熟的分布式事务解决方案,请参考文章《分布式事务框架Seata》
四、分布式事务的替代方案
分布式事务在使用中往往会遇到一些问题,包括:性能开销、实现复杂性、死锁、长时间锁定及网络不稳定等。这些问题使得确保各个参与者的数据一致性变得更加困难。
为了解决这些问题,常用的替代方案包括:
1. 消息队列:通过异步消息传递解耦服务,降低对事务的依赖。
2. 分布式锁:使用分布式锁管理资源访问,确保操作的顺序性。
3. 最终一致性:通过异步处理和补偿机制,实现系统在一定时间内达到一致状态。
这些方案能够提高系统的可用性和性能,同时减少分布式事务带来的复杂性。
参考链接:
https://xiaomi-info.github.io/2020/01/02/distributed-transaction/
https://blog.csdn.net/bjweimengshu/article/details/79607522
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)