分布式事务-Seata

目录

一、事务与分布式事务

1.事务

2.分布式事务

二、分布式事务问题的理论模型

1.X/Open分布式事务模型

2.两阶段提交协议

3.三阶段提交协议

4.CAP定理和BASE理论

CAP定理

BASE理论

三、分布式事务问题的常见解决方案

1.TCC补偿型方案

2.基于可靠性消息的最终一致性方案

3.最大努力通知型

四、分布式事务框架Seata

1.AT模式

2.Saga模式

Saga的优劣势

Saga的实现方式

五、AT模式Dubbo集成Seata

六、Seata  AT模式的实现原理

1.AT模式第一阶段的实现原理

2.AT模式第二阶段的原理分析

事务提交

事务回滚


一、事务与分布式事务

1.事务

提到事务这个概念,第一时间想到的是数据库的事务。所谓的数据库事务是指作为单个逻辑工作单元执行的多个数据库操作,要么同时成功,要么同时失败,它必须满足ACID特性,即:

  • 原子性(Atomicity):事务必须是原子工作单元,不可继续分割,要么全部成功,要么全部失败
  • 一致性(Consistency):事务完成时,所有的数据都必须保持一致
  • 隔离性(Isolation):由并发事务所做的修改必须与任何其他并发事务所做的修改隔离
  • 持久性(Durability):事务执行完成之后,它对于系统的影响是永久性的

2.分布式事务

在微服务架构下,随着业务服务的拆分及数据库的拆分,以下单业务举例:订单和库存分别拆分为两个独立的数据库,当客户端发起一个下单操作时,需要在订单服务对应的数据库中创建订单,同时需要基于RPC通信调用库存服务完成商品库存的扣减。由于每个数据库的事务执行情况只有自己知道,这样可能会导致订单数据库和库存数据库的数据不一致,比如订单创建成功,库存扣减失败。这就是所谓的分布式事务场景。精确来说,分布式事务是指事务的参与者、支持事务的服务器、资源服务器及事务管理器分别位于分布式系统的不同节点上。

二、分布式事务问题的理论模型

1.X/Open分布式事务模型

X/Open是一套分布式事务的标准,这个标准提出了使用两阶段提交来保证分布式事务的完整性

X/Open中包含以下三种角色:

  • AP:Application,表示应用程序
  • RM:Resource  Manager,表示资源管理器,比如数据库
  • TM:Transaction  Manager,表示事务管理器,一般指事务协调者,负载协调和管理事务,提供AP编程接口或管理RM。

实现的步骤如下:

  • 配置TM,把多个RM注册到TM,相当于TM注册RM作为数据源
  • AP从TM管理的RM中获取连接,如果RM是数据库则获取JDBC连接
  • AP向TM发起一个全局事务,生成全局事务ID(XID),XID会通知各个RM
  • AP通过第二步获得的连接直接操作RM完成数据操作。这时,AP在每次操作时会把XID传递给RM
  • AP结束全局事务,TM会通知各个RM全局事务结束
  • 根据各个RM的事务执行结果,执行提交或者回滚操作

需要注意的是,TM和多个RM之间的事务控制,是基于XA协议来完成的。XA协议是X/Open提出的分布式事务处理规范。目前Oracle、MySQL、DB2都实现了XA接口,所以它们都可以作为RM

2.两阶段提交协议

TM实现了多个RM事务的管理,实际上会涉及两个阶段的提交,第一阶段是事务的准备阶段,第二阶段是事务的提交或者回滚阶段,这两个阶段都是由事务管理器发起的。流程如下:

  • 准备阶段:事务管理器(TM)通知资源管理器(RM)准备分支事务,记录事务日志,并告知事务管理器的准备结果
  • 提交/回滚阶段:如果所有的资源管理器(RM)在准备阶段都明确返回成功,则事务管理器(TM)向所有的资源管理器(RM)发起事务提交指令完成数据的变更。反之,如果任何一个资源管理器(RM)明确返回失败,则事务管理器(TM)会向所有资源管理器(RM)发送事务回滚指令

总结:两阶段提交将一个事务的处理过程分为投票和执行两个阶段,它的优点在于充分考虑到了分布式事务的不可靠因素,并且采用两阶段提交就把系统不可靠而导致事务提交失败的概率降到最小,当然,它存在以下缺点:

  • 同步阻塞:所有的RM都是事务阻塞型的,对于任何一次指令都必须要有明确的响应才能继续进行下一步,否则会处于阻塞状态,占用的资源一直被锁定
  • 过于保守:任何一个节点失败都会导致数据回滚
  • 事务协调者的单点故障:如果协调者在第二阶段出现了故障,那么其他的RM会一直处于锁定状态
  • “脑裂”导致数据不一致问题:在第二阶段中,事务协调者向所有的RM发送commit请求后,发生局部网络异常导致只有一部分RM接收到了commit请求,这部分RM收到请求后执行commit操作,但未收到commit请求的节点由于事务无法提交,导致数据出现不一致问题

3.三阶段提交协议

三阶段提交协议是两阶段提交协议的改进版,它利用超时机制解决了同步阻塞的问题,三阶段提交协议的具体步骤如下:

  • CanCommit(询问阶段):事务协调者向参与者发送事务执行请求,询问是否可以完成指令,参与者只需回答是或者不是即可,不需要做真正的事务操作,这个阶段会有超时中止机制
  • PreCommit(准备阶段):事务协调者会根据参与者的反馈结果决定是否继续执行:如果在询问阶段所有参与者都返回可以执行操作,则事务协调者会向所有参与者发送PreCommit请求,参与者收到请求后写redo和undo日志,执行事务操作但是不提交事务,然后返回ACK响应等待事务协调者下一步通知;如果在询问阶段任意参与者返回不能执行操作的结果,那么事务协调者会向所有参与者发送事务中断请求
  • DoCommit(提交或回滚阶段):这个阶段也会存在两种结果,仍然根据上一步的执行结果来决定DoCommit的执行方式:如果每个参与者在PreCommit阶段都返回执行成功,那么事务协调者会向所有参与者发起事务提交指令;如果参与者中的任一参与者返回失败,那么事务协调者就会发起指令来回滚事务

三阶段提交协议和两阶段提交协议相比有一些不同点:

  • 增加了一个CanCommit阶段,用于询问所有参与者是否可以执行事务操作并且响应,它的好处是,可以尽早发现无法执行操作而中止后续的行为
  • 在准备阶段之后,事务协调者和参与者都引入超时机制,一旦超时,事务协调者和参与者会继续提交事务,并且任务处于成功状态,因为在这种情况下事务默认为成功的可能性比较大

4.CAP定理和BASE理论

前面提到的两阶段提交和三阶段提交是XA协议解决分布式数据一致性问题的基本原理,但是这两种方案为了保证数据的强一致性,降低了可用性。

CAP定理

CAP定理,又叫布鲁尔定理。简单来说它是指在分布式系统中不可能同时满足一致性(C:Consistency)、可用性(A:Availability)、分区容错性(P:Partition Tolerance)这三个基本需求,最多同时满足两个。

  • C:数据在多个副本中要保持强一致,比如前面说的分布式数据一致性问题
  • A:系统对外提供的服务必须一直处于可用状态,在任何故障下,客户端都能在合理的时间内获得服务端的非错误响应
  • P:在分布式系统中遇到任何网络分区故障,系统仍能够正常对外提供服务

CAP定理证明,在分布式系统中,要么满足CP,要么满足AP。原因是网络通信并不是绝对可靠的,比如网络延时、网络异常等都会导致系统故障

  • AP:对于AP来说,相当于放弃了强一致性,实现最终的一致,这是很多互联网公司解决分布式数据一致性问题的主要选择
  • CP:放弃高可用性,实现强一致性。前面提到的两阶段提交和三阶段提交都采用这种方案,可能导致的问题是用户完成一个操作会等待较长的时间

BASE理论

BASE理论是由于CAP中一致性和可用性不可兼得而衍生出来的一种新的思想,BASE理论的核心思想是通过牺牲数据的强一致性来获得高可用性,它有如下三个特性:

  • Basically  Available(基本可用):分布式系统在出现故障时,允许损失一部分功能的可用性,保证核心功能的可用
  • Soft  State(软状态):允许系统中的数据存在中间状态,这个状态不影响系统的可用性,也就是允许系统中不同节点的数据副本之间的同步存在延时
  • Eventually  Consistent(最终一致性):中间状态的数据在经过一段时间之后,会达到一个最终的数据一致性

BASE理论并没有要求数据的强一致,而是允许数据在一段时间内是不一致的,但是数据最终会在某个时间点实现一致。

三、分布式事务问题的常见解决方案

1.TCC补偿型方案

TCC(Try-Confirm-Cancel)是一种比较成熟的分布式数据一致性解决方案,它实际上是把一个完整的业务拆分为如下三个步骤:

  • Try:这个阶段主要是对数据的校验或者资源的预留
  • Confirm:确认真正执行的任务,只操作Try阶段预留的资源
  • Cancel:取消执行,释放Try阶段预留的资源

其实TCC是一种两阶段提交的思想,第一阶段通过Try进行准备工作,第二阶段Confirm/Cancel表示Try阶段操作的确认和回滚。举个例子:在一个理财APP中,用户通过账户余额购买一个理财产品,这里涉及如下操作:

  • 在账户服务的Try方法中对实际申购金额进行冻结,Confirm方法把Try方法冻结的资金进行实际扣减,Cancel方法把Try方法冻结的资金进行解冻
  • 理财产品服务的Try方法中将本次申购的部分额度进行冻结,Confirm方法把Try方法冻结的额度进行实际扣减,Cancel方法把Try方法中冻结的额度进行释放

在一个主业务方法中,分别调用这两个服务对外提供的处理方法,这两个服务做实际处理时,会先调用Try方法来做资源预留,如果这两个方法处理都正常,TCC事务协调器就会调用Confirm方法对预留资源进行实际应用。如果TCC事务协调器一旦感知到任何一个服务的Try方法处理失败,就会调用各个服务的Cancel方法进行回滚,从而保证数据的一致性

在一些特殊情况下,比如理财产品服务宕机,没有收到TCC事务协调器的Cancel或者Confirm请求。这种情况下,TCC事务框架会记录一些分布式事务的操作日志,保存分布式事务运行的各个阶段和状态。TCC事务协调器会根据操作日志来进行重试,以达到数据的最终一致性

2.基于可靠性消息的最终一致性方案

基于可靠性消息的最终一致性方案主要是利用消息中间件(Kafka、RocketMQ、RobbitMQ)的可靠性机制来实现数据一致性的投递。具体的执行逻辑如下:

  • 生产者发送一个事务消息到消息队列上,消息队列只记录这条消息的数据,此时消费者无法消费这条消息
  • 生产者执行具体的业务逻辑,完成本地事务的操作
  • 接着生产者根据本地事务的执行结果发送一条确认消息给消息队列服务器,如果本地事务执行成功,则发送一条Commit消息,表示在第一步中发送的消息可以被消费,否则,消息队列服务器会把第一步存储的消息删除
  • 如果生产者在执行本地事务的过程中因为某些情况一直未给消息队列服务器发送确认,那么消息队列服务器会定时主动回查生产者获取本地事务的执行结果,然后根据回查结果来决定这条消息是否需要投递给消费者
  • 消息队列服务器上存储的消息被生产者确认后,消费者就可以消费这条消息,消息消费完成之后发送一个确认标识给消息队列服务器,表示该消息投递成功

注:因为消息队列可靠性投递机制的存在,如果消费者没有签收该消息,那么消息队列服务器会重复投递,从而实现生产者的本地数据和消费者的本地数据在消息队列的机制下达成最终一致

3.最大努力通知型

最大努力通知型是一种比较简单的柔性事务解决方案,比较适用于对数据一致性要求不高的场景,最典型的使用场景是支付宝支付结果通知,所谓最大努力通知,就是在商户端如果没有返回一个消息确认时,支付宝会不断进行重试,直到收到一个消息确认或者达到最大重试次数。

四、分布式事务框架Seata

Seata是一款开源的分布式事务解决框架,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。它提供了AT、TCC、Saga和XA事务模式,为开发者提供了一站式的分布式事务解决方案。TCC和XA前文讲过,下面介绍一下AT和Saga两种事务模式

1.AT模式

AT模式是Seata最主推的分布式事务解决方案,它是基于XA演进而来的一种分布式事务模式,所以它同样分为三大模块:TM、RM、和TC。其中TM和RM作为Seata的客户端与业务系统集成,TC作为Seata的服务器独立部署。TM表示事务管理器(Transaction Manager),它负责向TC注册一个全局事务,并生成一个全局唯一的XID。在AT模式下,每个数据库资源被当做一个RM(Resource  Manager),在业务层通过JDBC标准的接口访问RM时,Seata会对所有请求进行拦截。每个本地事务进行提交时,RM都会向TC(Transaction  Coordinator,事务协调器)注册一个分支事务。具体流程如下:

  • TM向TC注册全局事务,并生成全局唯一的XID
  • RM向TC注册分支事务,并将其纳入该XID对应的全局事务范围
  • RM向TC汇报资源的准备状态
  • TC汇总所有事务参与者的执行状态,决定分布式事务是全部回滚还是提交
  • TC通知所有的RM提交/回滚事务

AT模式和XA模式一样,也是一个两阶段提交事务模型,不过和XA相比,做了很多优化

2.Saga模式

Saga模式又称为长事务解决方案,主要描述的是在没有两阶段提交的情况下如果解决分布式事务问题。其核心思想是:把一个业务流程中的长事务拆分为多个本地短事务,业务流程中的每个参与者都提交真实的提交给该本地短事务,当其中一个参与者事务执行失败,则通过补偿机制补偿前面已经成功的参与者

Saga提供了以下两种补偿恢复方式:

  • 向后恢复,也就是上面提到的第二种工作模式,如果任一子事务执行失败,则把之前执行的结果逐一撤销
  • 向前恢复,也就是不进行撤销,而是对失败的事务进行重试,这种方式比较适合于事务必须要执行成功的场景

Saga的优劣势

优势:一阶段直接提交本地事务,没有锁等待,性能比较高,在事件驱动的模式下,短事务可以异步执行,补偿机制的实现比较简单

缺点:Saga并不提供原子性和隔离性支持,隔离性的影响比较大,比如用户购买了一个商品后系统赠送了一个优惠卷,如果用户已经把优惠卷使用啦,那么如果事务出现问题要回滚就会出现问题

Saga的实现方式

事件/编排式:把Saga的决策和执行顺序逻辑分布在Saga的每一个参与者中,它们通过交换事件的方式来进行沟通。第一个服务执行完一个本地事务之后,发送一个事件。这个事件会被一个或者多个服务监听,监听到该事件的服务在执行本地事务并发布新的事件,直到该流程中最后一个服务的本地事务执行结束,才意味着整个分布式长事务执行结束。中间某个事务执行失败,会发布一个失败的事件,其他服务根据实际情况进行回滚

命令/协同式:把Saga的决策和执行顺序逻辑集中在一个Saga协调器中,它以命令/回复的方式与每项服务进行通信,告诉他们该执行哪些操作。需要注意的是,Saga协调器必须提前知道业务的所有流程,并且在整个流程中任何一个环节执行失败,它都需要向每个参与者发送命令撤销之前的事务操作

五、AT模式Dubbo集成Seata

通过一个电商平台的购买逻辑,基于Dubbo集成Seata实现一个分布式事务的解决方案。在整个业务流程中,会涉及三个服务:1.订单服务(用于创建订单)、2.账户服务(从账户中扣除余额)、3.库存服务(扣减指定商品的库存数量)

  • 基于Spring Boot+Nacos+Dubbo的项目结构,分别构建以下项目:订单服务sample-order-service、库存服务sample-repo-service、账户服务sample-account-service、公共服务组件sample-seata-common、提供统一业务的rest接口服务sample-rest-web
  • 创建三个数据库:seata_order、seata_repo、seata_account
  • sample-order-service订单服务负责创建订单,并且在创建订单之前先基于Dubbo协议调用账户服务的资金扣减接口;sample-repo-service库存服务提供库存扣减功能;sample-account-service实现账户服务提供余额扣减的功能。这三个服务需要集成MyBatis。sample-rest-web是基于Spring Boot的Web项目,主要用于对外提供业务的REST接口,它会分别调用库存服务和订单服务
  • 整合Seata实现分布式事务,分别在上面4个项目中添加Seata的Starter组件的依赖(seata-spring-boot-starter)
  • 添加Seata配置项目,在4个项目的application.yml文件中添加Seata的配置项
  • 添加回滚日志表,分别在3个数据库seata_order、seata_repo、seata_account中添加一张回滚日志表,用于记录每个数据库表操作的回滚日志,当某个服务的事务出现异常时会根据该日志进行回滚
  • sample-rest-web增加全局事务控制,需要做两件事:1.增加@GlobalTransactional全局事务注解。2.模拟一个异常处理,当商品编号等于某个指定的值时抛出异常,触发整个事务的回滚。
  • 启动服务测试

六、Seata  AT模式的实现原理

1.AT模式第一阶段的实现原理

  • 对业务的SQL进行解析,得到SQL的类型(增删改查)、表(表名)、条件(where后)等相关信息
  • 查询修改之前的数据镜像,根据解析得到的条件信息生成查询语句,定位数据
  • 执行业务SQL
  • 查询修改之后的数据镜像,根据前镜像结果,通过主键定位数据
  • 插入回滚日志:把前、后镜像数据及业务SQL相关的信息组成一条回滚日志记录,插入回滚日志表中
  • 提交前,向TC注册分支事务
  • 本地事务提交:业务数据的更新和回滚表中生成的记录一并提交
  • 将本地事务提交的结果上报给TC

2.AT模式第二阶段的原理分析

事务提交

  • 分支事务收到TC的提交请求后把请求放入一个异步任务队列中,并马上返回提交成功的结果给TC
  • 从异步队列中执行分支,提交请求,批量删除相应回滚日志表中的日志记录

事务回滚

  • 通过XID和branch ID查找到响应的回滚日志记录
  • 数据校验:拿表中的afterImage镜像数据与当前业务表中的数据进行比较,如果不同,说明数据被当前全局事务之外的动作做了修改,那么事务将不会回滚
  • 如果afterImage镜像数据和当前业务表中对应的数据相同,则表中的beforeImage镜像数据和业务SQL的相关信息生成回滚语句并执行
  • 提交本地事务,并把本地事务的执行结果(即分支事务回滚结果)上报给TC
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值