先上分布式事务架构图:
名词解释
①全局事务:当事务由全局事务管理器进行全局管理时成为全局事务,事务管理器负责管理全局的事务状态和参与的资源,协同资源的一致提交回滚
②TX协议:应用或者应用服务器与事务管理器的接口
③XA协议:全局事务管理器与资源管理器的接口。XA是由X/Open组织提出的分布式事务规范,该规范主要定义了全局事务管理器和局部资源管理器之间的接口
④RM(Resource Manager):资源管理器,负责控制和管理实际的资源,比如数据库资源、MQ
⑤TM(Transaction Manager):事务管理器,负责协调和管理事务,提供给AP编程接口以及管理资源管理器。事务管理器控制着全局事务,管理事务的生命周期,并且协调资源
⑥CAP理论:用于描述分布式系统在面对网络分区时的权衡
C(consistency),一致性(分布式事务中一般指的是强一致性),所有节点在同一时间看到相同的数据
A(availablity),可用性,每个请求都能在有限的时间内得到响应
P(partition tolerance),分区容错性,即使网络分区发生,系统仍然能够继续运行。
CAP 理论的核心观点是不可能同时满足所有三个特性:在分布式系统中,当网络分区发生时,系统只能在一致性和可用性之间选择一个来保证。换句话说,系统在面对网络分区时,必须在一致性和可用性之间做出权衡。
分区容忍性是必须的:在现代分布式系统中,分区容忍性通常被认为是必须的,因为网络分区是不可避免的。因此,系统设计者通常需要在一致性和可用性之间做出选择.
⑦BASE理论:它是对 CAP 理论的补充和扩展
BA(Basically Available),基本可用,即使在部分故障或异常情况下,系统仍然能够对外提供服务,但可能性能下降或部分功能不可用
S(soft state),软状态,系统中的数据可以在一段时间内保持中间状态
E(eventually consistent),最终一致性,系统中的所有数据副本在经过一段时间的同步后,最终能够达到一致状态
- 什么是分布式事务
- CAP理论
- BASE理论---CAP理论中AP方案的延伸
- 刚性事务(CP)
- 基于XA协议的两阶段提交2PC
- 2PC升级版 - 3PC
- 柔性事务(AP)
- 补偿型-TCC
- 异步确保型-MQ半消息方案
- 异步确保型-DB本地消息表
什么是分布式事务
分布式事务指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。
简单的说,在分布式系统上一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务节点上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。
典型的分布式事务场景:
1、跨库事务,一个应用某个功能需要操作多个库,不同的库中存储不同的业务数据
2、分库分表,当表的数据量达到一定量之后,会进行分库分表分开存储数据
3、微服务化,跨服务的对多个数据库的操作需要保证事务的全失败或者全成功
CAP理论
CAP理论是指计算机分布式系统的三个核心特性:一致性(Consistency)、可用性(Availability)和分区容错性(Partition Tolerance)。
1、一致性(强一致性):数据一致性可以分为强一致性、最终一致性、弱一致性。强一致性是指时刻保证客户端看到的数据都是一致的。如果允许存在中间状态,只要求经过一段时间后数据最终是一致的就是最终一致性。此外,如果允许存在部分数据不一致,那么就称之为弱一致性。
2、可用性:系统提供的服务必须一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。
3、分区容错性:当网络分区发生时,系统仍然能够正常工作。网络分区是指系统中的某些节点之间无法进行通信,但系统仍然需要继续提供服务
CAP理论认为,分布式系统最多只能同时满足其中的两个特性,而无法同时满足全部三个特性。这是因为在分布式系统中,网络分区和节点故障是不可避免的,而保证一致性和可用性需要跨节点协调,这会增加网络延迟和系统复杂度。
CAP的取舍,首先为什么不能放弃P,是因为放弃P就等于放弃了分布式,放弃了扩展性,而分布式事务本来就是基于分布式才出现的。放弃A选择CP,即放弃可用性,保证一致性和分区容错性。这种策略适用于对数据一致性要求较高的系统中,像一般涉及到金钱相关的业务,采用强一致性的机制,保证数据的高度一致性。而放弃C选择AP,即放弃一致性,保证可用性和分区容错性,这也是现在大多数互联网应用所采取的策略,因为现在集群规模越来越大,如果选择C的话会导致大量用户使用不了。
BASE理论---CAP理论中AP方案的延伸
CAP是分布式系统设计理论,BASE是CAP理论中AP方案的延伸,对于C我们采用的方式和策略就是保证最终一致性;
1、BA基本可用:由于网络不稳定和节点故障等因素,系统仍然要保证基本的可用性,尽力保证核心功能的正常运行
2、S软状态:允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时
3、E最终一致性:强调系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。其本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。
BASE理论是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的总结, 是基于CAP定理逐步演化而来的。BASE理论的核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。BASE理论其实就是对CAP理论的延伸和补充,主要是对AP的补充。牺牲数据的强一致性,来保证数据的可用性,虽然存在中间装填,但数据最终一致。
刚性事务(CP)
刚性事务指的是,要使分布式事务,达到像本地式事务一样,具备数据强一致性,从CAP来看,就是说,要达到CP状态。
刚性事务:XA 协议(2PC、JTA、JTS)、3PC,但由于同步阻塞,处理效率低,不适合大型网站分布式场景。
基于XA协议的两阶段提交2PC
X/Open DTP模型:是X/Open组织定义的一套分布式事务处理的标准,包括应用程序(AP)、资源管理器(RM)和事务管理器(TM)三个角色。DTP模型定义了分布式事务处理的框架和角色之间的关系。
XA规范:是X/Open DTP模型中定义的事务管理器(TM)和资源管理器(RM)之间的接口规范。XA规范使用两阶段提交协议来保证分布式事务的一致性。它主要定义了TM和RM之间的通信接口,以便协调事务的提交和回滚。
2PC解决的是分布式数据强一致性问题,2PC的大致流程:
2PC的特点:
①首先两阶段提交方案比较适合单体应用,并且是并发量不高的系统。
②性能问题:从流程上我们可以看得出,其最大缺点就在于它的执行过程中间,节点都处于阻塞状态。各个操作数据库的节点此时都占用着数据库资源,只有当所有节点准备完毕,事务协调者才会通知进行全局提交,参与者进行本地事务提交后才会释放资源。这样的过程会比较漫长,对性能影响比较大。
③协调者单节点故障问题:事务协调者是整个XA模型的核心,一旦事务协调者节点挂掉,会导致参与者收不到提交或回滚的通知,从而导致参与者节点始终处于事务无法完成的中间状态。
④数据不一致的问题:协调者向部分参与者发起commit后宕机了,会导致部分参与者收不到commit指令导致数据不一致问题
2PC升级版 - 3PC
针对2PC的缺点,研究者提出了3PC,即Three-Phase Commit。作为2PC的改进版,3PC将原有的两阶段过程,重新划分为CanCommit、PreCommit和do Commit三个阶段。
3PC主要解决的单点故障问题:
相对于2PC,3PC主要解决的单点故障问题,并减少阻塞, 因为一旦参与者无法及时收到来自协调者的信息之后,他会默认执行commit。而不会一直持有事务资源并处于阻塞状态。
但是这种机制也会导致数据一致性问题,因为,由于网络原因,协调者发送的abort响应没有及时被参与者接收到,那么参与者在等待超时之后执行了commit操作。这样就和其他接到abort命令并执行回滚的参与者之间存在数据不一致的情况。
"3PC相对于2PC而言到底优化了什么地方呢?"
相比较2PC而言,3PC对于协调者(Coordinator)和参与者(Partcipant)都设置了超时时间,而2PC只有协调者才拥有超时机制。这解决了一个什么问题呢?
这个优化点,主要是避免了参与者在长时间无法与协调者节点通讯(协调者挂掉了)的情况下,无法释放资源的问题,因为参与者自身拥有超时机制会在超时后,自动进行本地commit从而进行释放资源。而这种机制也侧面降低了整个事务的阻塞时间和范围。
另外,通过CanCommit、PreCommit、DoCommit三个阶段的设计,相较于2PC而言,多设置了一个缓冲阶段保证了在最后提交阶段之前各参与节点的状态是一致的。
以上就是3PC相对于2PC的一个提高(相对缓解了2PC中的前两个问题),但是3PC依然没有完全解决数据不一致的问题。假如在 DoCommit 过程,参与者A无法接收协调者的通信,那么参与者A会自动提交,但是提交失败了,其他参与者成功了,此时数据就会不一致。
柔性事务(AP)
柔性事务有两个特性:基本可用和柔性状态。
- 基本可用是指分布式系统出现故障的时候允许损失一部分的可用性。
- 柔性状态是指允许系统存在中间状态,这个中间状态不会影响系统整体的可用性,比如数据库读写分离的主从同步延迟等。柔性事务的一致性指的是最终一致性。
柔性事务可分为补偿型、异步确保型、最大努通知型
柔型事务:TCC、Saga、MQ消息事务(半消息)、本地事务消息
补偿型-TCC
基于消息实现的事务并不能解决所有的业务场景,例如以下场景:某笔订单完成时,同时扣掉用户的现金。这里事务发起方是管理订单库的服务,但对整个事务是否提交并不能只由订单服务决定,因为还要确保用户有足够的钱,才能完成这笔交易,而这个信息在管理现金的服务里。这里我们可以引入基于补偿实现的事务,其流程如下:
- 创建订单数据,但暂不提交本地事务
- 订单服务发送远程调用到现金服务,以扣除对应的金额
- 上述步骤成功后提交订单库的事务
补偿模式使用一个额外的协调服务来协调各个需要保证一致性的业务服务,协调服务按顺序调用各个业务微服务,如果某个业务服务调用异常(包括业务异常和技术异常)就取消之前所有已经调用成功的业务服务。
TCC是Try、Confirm、Cancel三个词语的缩写,TCC要求每个分支事务实现三个操作:预处理Try、确认Confirm、撤销Cancel。
- 初步操作 Try:完成所有业务检查,预留必须的业务资源。
- 确认操作 Confirm:真正执行的业务逻辑,不作任何业务检查,只使用 Try 阶段预留的业务资源。因此,只要 Try 操作成功,Confirm 必须能成功。另外,Confirm 操作需满足幂等性,保证分布式事务有且只能成功一次。并且也需要满足幂等性。
- 取消操作 Cancel:释放 Try 阶段预留的业务资源。同样的,Cancel 操作也需要满足幂等性。
Try阶段失败了可以cancel进行回滚,而如果是Comfirm和cancel阶段失败的话,TCC 中会添加事务日志,如果 Confirm 或者 Cancel 阶段出错,则会进行重试,所以这两个阶段需要支持幂等;如果重试失败,则需要人工介入进行恢复和处理等
优缺点:
①可以解决部分场景下的分布式事务
②它的一个问题在于,需要每个参与者都分别实现Try,Confirm和Cancel接口及逻辑,这对于业务的侵入性是巨大的,并且严重依赖回滚和补偿代码,所以,TCC 方案的使用场景较少,但是也有使用的场景。比如说跟钱打交道的,支付、交易相关的场景,大家会用 TCC方案,严格保证分布式事务要么全部成功,要么全部自动回滚,严格保证资金的正确性,保证在资金上不会出现问题
异步确保型-MQ半消息方案
执行流程:
①事务发起方发送半消息到MQ
②MQ收到消息后,回复一个ACK确认收到消息
③事务发起方开始执行本地事务,将执行结果(是commit还是rollback),发送消息到MQ中
④如果MQ收到的是rollback,则将消息丢弃不消费。如果是commit,则将消息标记为可消费状态,可投递到消费者处消费
⑤消费者收到消息,执行自己的本地事务,执行本地事务会发生各种情况(消费成功commit、消费失败rollback、网络故障、消费者挂掉、以及超时等)
⑥如果是消费成功commit---则将消息标记为已消费状态,不被再次消费
如果是消费失败包括rollback、网络、超时问题,会有消费成功机制(消息确认机制和失败重试机制)来保证执行成功
此外应注意两点:
①消息回查机制:网络断开或生产者重启可能会导致丢失事务消息的第二次确认。所以当MQ Server发现消息长时间处于半消息状态时,将向消息生产者发送请求,询问该消息的最终状态是提交还是回滚。
②消费幂等性:所有消息队列的设计都不保证消息消费不重复,所以需要我们注意消费幂等性的考虑和设计,实现幂等性的方案:
优缺点:
①通过异步解耦的方式,实现了最终一致性,保证了了分布式事务
②需要涉及到消息回查和幂等性设计
异步确保型-DB本地消息表
发送消息方:
会去创建一个消息表,记录着消息状态的相关信息。
业务数据和消息表在同一个数据库,要保证它俩在同一个本地事务。业务操作完之后直接利用本地事务,将业务数据和事务消息直接写入数据库。
在本地事务中处理完业务数据和写消息表操作后,通过写消息到 MQ 消息队列。使用专门的投递工作线程(定时任务)进行事务消息投递到MQ,根据投递ACK去删除事务消息表记录
消息会发到消息消费方,如果发送失败,即进行重试。并且通过消息确认机制保证消费者正常消费消息,并且消费消息也要设计消息幂等性问题
消息消费方:
处理消息队列中的消息,完成自己的业务逻辑。
如果本地事务处理成功,则表明已经处理成功了。
如果本地事务处理失败,那么就会重试执行。
如果是业务层面的失败,给消息生产方发送一个业务补偿消息,通知进行回滚等操作。
优缺点:
①建设成本较低,无需回查,代码侵入性较低。
②但是本地消息表会跟业务表耦合,另外因为是依赖于DB,高并发场景下会有性能瓶颈,而且也需要考虑消息消费的幂等性
至于异步确保型的Saga方案、最大努力通知型的MQ消息方案和DB本地表方案暂时不研究了。
Seata
本文参考一篇非常棒优秀的文章:分布式事务圣经 ,非常推荐去看多看!!!