分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】

目录

一、分布式事务的问题

1. 本地事务

2. 分布式事务

介绍

示例场景

3. 分布式事务的问题演示

准备数据库

导入演示项目

启动服务

测试下单功能

4. 小结

二、CAP定理和BASE理论【面试】

CAP定理

CAP三指标介绍

CAP的矛盾

BASE理论

​分布式事务的解决思路

解决思路

几个概念

小结

三、Seata入门与整合

1.Seata简介

2.Seata架构

3.Seata部署

下载与安装

准备数据库

配置

启动TC服务

4. 微服务集成Seata

添加依赖

配置tc地址

5. 小结

四、Seata的事务模式

1. XA模式

两阶段提交

Seata的XA模型

XA模式的优缺点

使用示例

2. AT模式【重点】

Seata的AT模型

AT与XA的区别

脏写问题

AT模式的优缺点

使用示例【掌握】

3. TCC模式

TCC模式的实现流程

Seata的TCC模式

优缺点

TCC的几个问题

使用示例

4. SAGA模式

原理说明

优缺点

5. 四种模式对比

6. 小结

五、Seata高可用【拓展】

1.Seata高可用架构模型

2. 实现高可用


 

一、分布式事务的问题

  • 复习本地事务
  • 了解分布式事务问题

1. 本地事务

事务概念:即传统的单机事务,是数据库的概念,表示由一个或多个操作组成的一个业务。比如:银行转账

事务作用:组成事务的多个操作单元,在操作数据库时,要成功都成功,要失败都失败

事务特性:ACID

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第1张图片

  • 事务操作,底层会对数据加锁,会影响操作性能

  • 如果多个数据库操作要想属于同一个事务进行管理:就必须使用同一个数据库连接Connection对象

2. 分布式事务

介绍

在分布式环境上同样需要事务来保证数据的一致性。而因为跨数据源或跨服务环境所导致的传统事务不可用,形成的新的事务需求,这样的事务叫分布式事务。

传统事务中,要想让多个操作属于同一事务,就需要使用同一个数据库连接Connection对象。但是在分布式环境下,通常是做不到这一点的,必须使用分布式事务。比如:

  • 跨数据源的分布式事务:程序要操作不同服务器上的数据库

  • 跨服务的分布式事务:程序要调用多个服务,每个服务都要操作数据库

  • 综合情况

示例场景

电商行业中比较常见的下单付款案例,包括下面几个行为:

  • 创建新订单

  • 扣减商品库存

  • 从用户账户余额扣除金额

要完成上面的操作,需要访问三个不同的微服务和三个不同的数据库,如图:

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第2张图片

订单的创建、库存的扣减、账户扣款在每一个服务和数据库内是一个本地事务,可以保证ACID原则。

但是当我们把三件事情看做一个"业务",要满足保证“业务”的原子性,要么所有操作全部成功,要么全部失败,不允许出现部分成功部分失败的现象,这就是分布式系统下的事务要解决的问题了

3. 分布式事务的问题演示

准备数据库

使用SQLyog执行SQL脚本《seata-demo.sql》,初始化数据库

导入演示项目

资料里提供了《seata-demo》项目,把这个项目拷贝到你的工作空间目录里

用idea打开这个项目

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第3张图片

启动服务

  1. 启动nacos

  2. 启动所有微服务

测试下单功能

使用Postman发请求下单

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第4张图片

请求路径是:http://localhost:8082/order

请求方式是:POST

表单参数是:

  • userId:user202103032042012

  • commodityCode:100202003032041

  • count:20

  • money:200

最终结果是:因为库存量不够,导致扣减库存失败,但是用户的帐户余额已经扣减了。已经出现了分布式事务问题

    

    

   

4. 小结

 ​

分布式事务:
    跨数据源的事务
    跨服务的事务
    以上综合
分布式事务要求:
    无论是跨数据源还是跨服务,都要做到:要么一起成功,要么一起失败

    

二、CAP定理和BASE理论【面试】

  • 能描述CAP定理
  • 理解BASE理论

分布式事务问题的处理,其实就是在数据的一致性与服务的可用性之间做一个权衡:

  • 如果要保证所有子事务的数据一致性:就要舍弃一些服务的可用性。因为数据库事务会对数据行加锁

  • 如果要保证所有服务的可用性:就要考虑一下数据的一致性如何处理

解决分布式事务问题,需要一些分布式系统的基础知识作为理论指导

CAP定理

1998年,加州大学的计算机科学家 Eric Brewer 提出,分布式系统有三个指标:一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。 Eric Brewer 说,这三个指标不可能同时做到,这个结论就叫做 CAP 定理。 分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第5张图片

CAP三指标介绍

1.C一致性

一致性Consitency,即 用户访问分布式系统中的任意节点,得到的数据必须一致(业务上的一致)。这就要求节点之间必须要及时同步数据。

比如:集群中有两个节点,初始数据是一致的;当修改了其中一个节点的数据时,要把数据变更立即同步到另外一个节点,保证所有节点的数据是一致的。分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第6张图片

2.A可用性

 可用性Availability,即 用户访问集群中的任意健康节点,必须能得到响应,而不是超时或拒绝。 分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第7张图片

3.P分区容错性

分区Partition:因为网络故障或者其它原因,导致分布式系统中的部分节点与其它节点失联,形成独立分区。

分区容错性Partition Tolerance,即 集群出现分区时,整个系统也要持续对外提供服务

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第8张图片

CAP的矛盾

在分布式系统中,分区容错性(P)是必须要保证的。但C和A两个指标就互相矛盾

以上图为例:

  • 因为网络原因形成了两个分区:node01和node02一个分区;node03一个分区

  • 如果我们要修改node02上的数据:

    • 如果要追求一致性:必须等到node02把数据同步到node01、node03,才返回响应。但因为分区了,等待时间不确定,可能要长时间等待==>追求一致性C,舍弃了可用性A

    • 如果要追求可用性:修改了node02的数据就立即返回响应;不能保证数据同步到了node01和node03

      追求了可用性A,舍弃了一致性C

所以CAP定理中,P必须保证,而C和A相互矛盾,只能保证一个。即:

  • CP模式:舍弃可用性,追求一致性

  • AP模式:舍弃一致性,追求可用性

但是,难道这个AC矛盾就不可调和的吗?并不是,BASE理论就提出了完善和弥补的方案


BASE理论

BASE理论,是对CAP定理中的CA矛盾进行权衡之后,提供的一种解决思路。这是指:

  • 采用CP模式,追求一致性,舍弃一定的可用性:

    • BA (Basically Available),基本可用:分布式系统在出现故障时,允许损失部分可用性,要保证核心可用

      响应时间的损失:比如原本要求0.5秒内响应,现在允许5秒内响应

      系统功能的损失:出现某些故障时,核心功能保证可用,部分非核心功能允许不可用

  • 采用AP模式,追求可用性,对一致性采用一些补偿措施

    • S (Soft State),软状态:在一定时间内,允许出现中间状态,比如 数据临时不一致

    • E (Eventually Consistent),最终一致性:虽然无法保证强一致性,但是在软状态之后,最终达到数据一致


​分布式事务的解决思路

解决思路

分布式事务最大的问题是各个子事务的一致性问题,因此可以借鉴CAP定理和BASE理论。有两种解决思路:

  • AP模式:各子事务分别执行和提交,允许出现结果不一致,然后采用弥补措施恢复数据即可,实现最终一致。

  • CP模式:各个子事务执行后互相等待,同时提交,同时回滚,达成强一致。但事务等待过程中,处于弱可用状态。

几个概念

  • 分支事务RM:在整个业务中,每一个子系统的事务,称为一个分支事务。对应@Transactional

  • 全局事务TM:一个完整的业务,需要众多分支事务共同组成一个全局事务。对应@GlobalTransactional

  • 事务协调者TC:用于在整个全局事务里,管理、协调各个分支事务的状态。对应Seata软件

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第9张图片

小结

什么是CAP定理:
    理解CAP
        C:一致性。访问系统里任意一个节点,得到的数据必须是一致的
        A:可用性。访问系统里任意一个健康节点,都要立即返回响应,不能阻塞、不能拒绝
        P:分区容错性。如果系统出现分区(某些节点失联),整个系统必须仍然能够正常提供服务
    CAP定理:
        一个分布式系统最多只能做到CAP三个指标里的两个指标
        通常情况下,P是必须要满足的;然后A和C是矛盾的
            如果要追求A可用性:访问任意节点立即必须返回响应,就不能保证数据已经同步完成了。一致性不保证
            如果要追求C一致性:访问任意节点必须得到相同数据,就必须等待数据同步完成才能响应。可用性低了
什么是BASE理论:
    BASE理论是对CAP矛盾提出的一种解决思路
    BA:追求CP一致性,允许舍弃一定的可用性,只要做到基本可用BA即可
        允许响应时间稍有延长,允许非核心功能暂不可用
    SE:追求AP可用性,允许存在临时不一致的状态,只要做到最终一致即可
        S:软状态,表示数据临时不一致的状态
        E:最终一致,在一定时间内最终达到了数据的一致
分布式事务的解决思路:
    借鉴Base理论
    相关的一些概念:
        RM:Resource Manager,分支事务。对应代码里的@Transactional
        TM:Transaction Manager,全局事务。对应代码里的@GlobalTransactional
        TC:Transaction Coordinater,事务协调者,对所有分支事务进行协调管理的。对应软件Seata

三、Seata入门与整合

  • 了解Seata架构相关的角色
  • 能够安装部署Seata
  • 能够将微服务与Seata集成

1.Seata简介

Seata是 2019 年 1 月份蚂蚁金服和阿里巴巴共同开源的分布式事务解决方案。致力于提供高性能和简单易用的分布式事务服务,为用户打造一站式的分布式解决方案。

官网地址:http://seata.io/,其中的文档、博客中提供了大量的使用说明、源码分析。

2.Seata架构

Seata事务管理中有三个重要的角色:

  • TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。

    是Seata本身

  • TM (Transaction Manager) - 事务管理器:定义全局事务的范围、开启全局事务、提交或回滚全局事务。

    负责事务的边界。@GlobalTransactional

  • RM (Resource Manager) - 资源管理器:处理分支事务的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。@Transactional

    分支事务

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第10张图片

Seata基于上述架构提供了四种不同的分布式事务解决方案:

  • XA模式:强一致性分阶段事务模式,牺牲了一定的可用性,无业务侵入

  • AT模式:最终一致的分阶段事务模式,无业务侵入,也是Seata的默认模式

  • TCC模式:最终一致的分阶段事务模式,有业务侵入

  • SAGA模式:长事务模式,有业务侵入

无论哪种方案,都离不开TC,也就是事务的协调者。

3.Seata部署

 seata-server中分布式事务中充当了TC的角色

下载与安装

下载

下载seata-server包,地址 下载中心

也可以直接使用资料里提供好的程序:《seata-server-1.4.2.zip》

安装

seata-server免安装,直接解压到一个不含中文、空格、特殊字符的目录里即可

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第11张图片


准备数据库

tc服务在管理分布式事务时,需要记录事务相关数据到数据库中,包括全局事务、分支事务、全局锁等信息,因此要提前创建好这些表:

用Navicat或其它工具连接本机MySQL,执行脚本:《seata-tc-server.sql》

配置

1.在nacos里添加配置

注意,为了让tc服务的集群可以共享配置,我们选择了nacos作为统一配置中心。因此服务端配置文件seataServer.properties文件需要在nacos中配好

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第12张图片

在nacos中新建配置:

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第13张图片

配置的内容如下:

# 数据存储方式,db代表数据库
store.mode=db
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useSSL=false&useUnicode=true&rewriteBatchedStatements=true&serverTimezone=UTC
store.db.user=root
store.db.password=root
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000
# 事务、日志等配置
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000

# 客户端与服务端传输方式
transport.serialization=seata
transport.compressor=none
# 关闭metrics功能,提高性能
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898

2.seata拉取配置文件并注册服务

修改conf目录下的 registry.conf文件,完整配置如下:
registry {
  # tc服务的注册中心类型,使用nacos
  type = "nacos"

  # 将tc服务注册到nacos,要配置nacos的地址等信息。 ""@DEFAULT_GROUP@seata-tc-server@TJ
  nacos {
    # tc服务的应用名称,可以自定义
    application = "seata-tc-server"
    serverAddr = "127.0.0.1:8848"
    group = "DEFAULT_GROUP"
    namespace = ""
    cluster = "TJ"
    username = "nacos"
    password = "nacos"
  }
}

config {
  # 读取tc配置文件的方式:从配置中心nacos里读取配置。这样的话,如果tc搭建集群,可以通过配置中心共享配置
  type = "nacos"

  # 要从nacos读取配置文件信息,要配置nacos的地址等信息
  nacos {
    serverAddr = "127.0.0.1:8848"
    namespace = ""
    group = "SEATA_GROUP"
    username = "nacos"
    password = "nacos"
    dataId = "seataServer.properties"
  }
}

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第14张图片

 分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第15张图片

启动TC服务

  1. 先启动nacos

  2. 启动seata:

    进入seata的bin目录,运行其中的seata-server.bat分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第16张图片

    验证是否启动:

    如果启动成功了,seata-server应该已经注册到nacos注册中心了

    我们打开nacos,看一下有没有seata服务

    分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第17张图片

4. 微服务集成Seata

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第18张图片

 每个需要分布式事务的微服务,都要按照下面的步骤进行配置。

我们以订单服务order-service为例进行说明;其它微服务也要做相同配置

添加依赖

修改pom.xml,添加依赖



    com.alibaba.cloud
    spring-cloud-starter-alibaba-seata
    
        
        
            seata-spring-boot-starter
            io.seata
        
    


    io.seata
    seata-spring-boot-starter
    
    1.4.2

配置tc地址

修改application.yaml,配置tc地址。通过注册中心nacos,可以拉取tc服务的地址

seata:
  # 要去注册中心nacos里,拉取tc服务的地址
  registry:
    type: nacos
    # tc服务集群注册到了nacos的""@DEFAULT_GROUP@seata-tc-server@TJ
    # 所以要从nacos中拉取 ""@DEFAULT_GROUP@seata-tc-server@TJ  服务集群
    nacos:
      server-addr: localhost:8848 #nacos地址
      namespace: "" #名称空间,没有设置,用""
      group: DEFAULT_GROUP #分组,没有设置,默认用DEFAULT_GROUP
      application: seata-tc-server #seata服务名称
      username: nacos
      password: nacos
  tx-service-group: seata-demo #事务组名称
  service:
    vgroup-mapping: #事务组与cluster的映射关系
      seata-demo: TJ

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第19张图片

 每个配置文件修改后启动  测试:如下图就代表配置就没有问题了

    

   

5. 小结

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第20张图片分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第21张图片

四、Seata的事务模式

  • 理解并使用Seata的XA模式
  • 理解并使用Seata的AT模式【重点】
  • 理解并使用Seata的TCC模式
  • 了解Seata的SAGA模式

下面我们就一起学习下Seata中的四种不同的事务模式。

1. XA模式

XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准,XA 规范 描述了全局的TM与局部的RM之间的接口,几乎所有主流的数据库都对 XA 规范 提供了支持。
 

两阶段提交

XA是规范,目前主流数据库都实现了这种规范,实现的原理都是基于两阶段提交:

  • 一阶段:

    事务协调者通知每个事务参与者执行其本地事务

    本地事务执行后暂不提交,继续持有数据库锁;向事务协调者报告事务的执行状态

  • 二阶段:

    事务协调者基于一阶段的报告来决定下一步操作

    如果一阶段所有事务都成功:则通知所有事务参与者都提交事务

    如果一阶段有事务执行失败:则通知所有事务参与者都回滚事务

如图:

  • 如果所有事务都正常:

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第22张图片 如果有事务出现异常: 分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第23张图片

    

Seata的XA模型

Seata对原始的XA模式做了简单的封装和改造,以适应自己的事务模型

  • 一阶段-RM工作:

    注册分支事务到TC

    执行分支业务的SQL但不提交

    向TC报告事务执行状态

  • 二阶段-TC工作

    TC检测各分支事务的执行状态

    如果都成功:TC通知所有RM提交事务

    如果有失败:TC通知所有RM回滚事务

  • 二阶段-RM工作

    根据TC的通知指定,提交或回滚事务

Seata的XA基本架构如图:

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第24张图片

    

XA模式的优缺点

XA模式的优点:

  • 事务的强一致性,满足ACID原则。

  • 常用数据库都支持,实现简单,并且没有代码侵入

XA模式的缺点:

  • 性能较差,因为一阶段需要锁定数据库资源,等待二阶段结束才释放,所以性能较差

  • 依赖关系型数据库实现事务。NoSQL参与不进来

    

使用示例

 Seata的依赖启动器已经完成了XA模式的自动装配,使用起来非常简单,步骤:

 设置XA模式 修改微服务配置文件:

  1. 修改配置文件,开启XA模式

  2. 修改全局事务入口方法,添加注解@GlobalTransactional注解:TM全局事务

    每个分支事务的方法上,添加注解@Transactional注解:RM分支事务

  3. 重启测试

1) 开启XA模式

修改每个参与事务的微服务的配置文件,开启XA模式:

seata:
  data-source-proxy-mode: XA

2) 添加注解@GlobalTransactional

在发起全局事务的入口方法上添加注解@GlobalTransactional

在本例中是OrderServiceImpl中的create方法

@Override
@GlobalTransactional
public Long create(Order order) {
    // 创建订单
    orderMapper.insert(order);
    try {
        // 扣用户余额
        accountClient.deduct(order.getUserId(), order.getMoney());
        // 扣库存
        storageClient.deduct(order.getCommodityCode(), order.getCount());

    } catch (FeignException e) {
        log.error("下单失败,原因:{}", e.contentUTF8(), e);
        throw new RuntimeException(e.contentUTF8(), e);
    }
    return order.getId();
}

3) 重启测试

重启所有微服务,再次测试分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第25张图片

 分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第26张图片

    


2. AT模式【重点】

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第27张图片

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第28张图片

Seata的AT模型

AT模式同样是分阶段提交的事务模型,不过缺弥补了XA模型中资源锁定周期过长的缺陷。

  • 一阶段-RM工作:

    向TC注册事务分支

    记录undo-log(数据变更之前的快照)

    执行业务SQL并提交

    向TC报告事务状态

  • 二阶段-TC工作:

    基于一阶段的报告来决定下一步操作

    如果所有分支事务都成功:通知所有RM提交事务

    如果任一分支事务失败了:通知所有RM回滚事务

  • 二阶段-RM工作:

    如果收到提交通知指令:删除undo-log

    如果收到回滚通知指令:根据undo-log恢复到更新前的数据

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第29张图片

AT与XA的区别

  • XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源。

  • XA模式依赖数据库机制实现回滚;       AT模式利用数据快照实现数据回滚。

  • XA模式强一致;                                    AT模式最终一致

    

脏写问题

多线程并发访问AT模式的分布式事务时,可能出现脏写问题。如图:分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第30张图片

解决思路就是引入了全局锁的概念。在释放DB锁之前,先拿到全局锁。避免同一时刻有另外一个事务来操作当前数据。 分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第31张图片 

AT模式的优缺点

AT模式的优点:

  • 一阶段完成直接提交事务,释放数据库资源,性能比较好

  • 利用全局锁实现读写隔离

  • 没有代码侵入,框架自动完成回滚和提交

AT模式的缺点:

  • 两阶段之间属于软状态,属于最终一致

  • 框架的快照功能会影响性能,但比XA模式要好很多

使用示例【掌握】

 T模式中的快照生成、回滚等动作都是由框架自动完成,没有任何代码侵入,因此实现非常简单。

只不过,AT模式需要一个表来记录全局锁、另一张表来记录数据快照undo_log。

步骤:

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第32张图片

  1. 准备数据快照表

  2. 开启AT模式

  3. 重启并测试

1) 准备数据库表

执行脚本《undo_log表.sql》,把undo_log表导入到微服务的库。我们这里是seata-demo

这张表用于存储一阶段的undo日志,二阶段回滚时会使用这些日志进行数据恢复;二阶段提交时则直接清除日志

    

2) 开启AT模式

修改参与分布式事务的所有微服务的配置文件,将事务模式修改为AT模式

可以不配置,因为Seata默认使用的就是AT模式

seata:
  data-source-proxy-mode: AT

3) 添加注解

在全局事务的入口方法上添加注解@GlobalTransactional

我们这里在OrderServiceImplcreate方法上添加

    

4) 重启测试

  1. 重启所有微服务

  2. 使用Postman测试

3. TCC模式

TCC模式与AT模式非常相似,每阶段都是独立事务,不同的是TCC通过人工编码来实现数据恢复。需要实现三个方法:

  • Try:资源的检测和预留;

  • Confirm:完成资源操作业务;要求 Try 成功 Confirm 一定要能成功。

  • Cancel:预留资源释放,可以理解为try的反向操作。

    

TCC模式的实现流程

举例说明:减扣余额的业务。

  • 假设帐户A原本余额是100,需要减扣30元。

  • 要提前准备一个位置存储冻结金额,例如:创建一张数据库表,存储冻结的金额

    

一阶段(Try)

检查余额是否充足。如果余额充足,则扣除余额30元,在冻结金额里增加30元。

此时总金额 = 余额 + 冻结金额,总数仍然是100元不变,分支事务可以直接提交,无需等待其它事务

    

二阶段(Confirm)

如果TC通知要提交,则冻结金额-30,直接提交; 用户的余额不变

此时总金额 = 余额 + 冻结金额,总数是70

二阶段(Cancel)

如果TC通知要回滚,则释放冻结金额,恢复用户余额,即:冻结金额-30,用户余额+30

此时总金额 = 余额 + 冻结金额,总数是100

Seata的TCC模式

Seata中的TCC模型依然延续之前的事务架构,如图: 分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第33张图片

优缺点

TCC模式的每个阶段做什么:

  • Try:资源检查和预留

  • Confirm:业务执行和提交

  • Cancel:预留资源的释放

TCC的优点:

  • 一阶段完成直接提交事务,释放数据库资源,性能好

  • 相比AT模型,无需生成快照,无需使用全局锁,性能最强

  • 不依赖数据库事务,而是依赖补偿操作,可以用于非事务型数据库

TCC的缺点:

  • 有代码侵入,需要人为编写try、Confirm和Cancel接口,太麻烦

  • 软状态,事务是最终一致

  • 需要考虑Confirm和Cancel的失败情况,做好幂等处理

TCC的几个问题

    

空回滚

当某分支事务的try阶段阻塞时,可能导致全局事务超时而触发二阶段的cancel操作。在未执行try操作时先执行了cancel操作,这时cancel不能做回滚,就要允许空回滚

    

业务悬挂

对于已经空回滚的业务,之前被阻塞的try操作恢复,继续执行try,就永远不可能confirm或cancel ,事务一直处于中间状态,这就是业务悬挂

执行try操作时,应当判断cancel是否已经执行过了,如果已经执行,应当阻止空回滚后的try操作,避免悬挂

    

幂等性

当TC通知RM提交或回滚时,如果RM明明已经提交或回滚,但是因为某些原因(例如网络拥堵)导致没有给TC返回结果,TC会重复通知RM提交或回滚,直到收到结果为止。                

为了避免Try或Confirm业务的重复执行,Try和Confirm需要实现幂等:判断一下事务的状态,如果已经处理过,就直接返回成功,结束即可。

    

    

使用示例

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第34张图片

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第35张图片

我们使用AT和TCC混合使用的方式进行演示:

  • 用户余额处理适合使用TCC,就使用TCC模式

  • 库存处理也适合使用TCC,但是我们TCC比较麻烦,就不处理了,仍然使用AT

  • 创建订单不适合使用TCC,还使用AT模式

解决空回滚和业务悬挂问题,必须要记录当前事务状态,是在try、还是cancel。

步骤:

  1. 定义一张表,用于存储冻结金额和事务状态

  2. 定义Try业务、Confirm业务和Cancel业务,并处理业务悬挂和空回滚问题

    

1) 创建表存储事务状态和冻结数据

在微服务的数据库(我们这里是seata-demo库)里创建表,如下:

CREATE TABLE `account_freeze_tbl`  (
  `xid` VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `user_id` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `freeze_money` INT(11) UNSIGNED NULL DEFAULT 0,
  `state` INT(1) NULL DEFAULT NULL COMMENT '事务状态,0:try,1:confirm,2:cancel',
  PRIMARY KEY (`xid`) USING BTREE
) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT;

其中:

  • xid:全局事务的id

  • user_id:用户id,即 哪个用户的数据

  • freeze_money:冻结金额

  • state:事务状态

    

2) 实现Try、Confirm和Cancel业务

Try业务:

  • 先根据xid查询account_freeze_tbl表数据,如果找到了说明Cancel已执行,拒绝执行Try业务

  • 如果找不到:

    • 把冻结金额和事务状态保存到account_freeze_tbl表里

    • 减扣帐户表的余额

Confirm业务:

  • 根据xid,删除记录(冻结金额就删除掉了)

Cancel业务:

  • 根据xid先查询account_freeze_tbl表数据,如果找不到说明try还没有做,需要空回滚

  • 如果找到了:

    • 修改account_freeze_tbl表:冻结金额为0,state为2(cancel)

    • 修改帐户表,恢复余额

    

声明TCC接口

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第36张图片

 TCC的Try、Confirm、Cancel方法都需要在接口中基于注解进行声明

修改帐户服务account-service,利用TCC实现余额扣减功能:

  • com.itheima.order.service包里创建接口:

  • 注意在接口上添加@LocalTCC注解

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第37张图片

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第38张图片

/*
 * 这个接口,是用于让Seata扫描,告诉Seata一些TCC相关的配置。需要
 * 1.接口上添加@LocalTCC
 * 2.在接口里定义好Try Confirm Cancel三个方法,方法名称随意
 *   需要我们使用注解@TwoPhaseBusinessAction配置一下,告诉Seata哪里是Try、哪个是Confirm、哪个是Cancel
 *   注解在Try方法上,注解要求配置
 *          name:唯一标识
 *          commitMethod:提交方法是哪个(Confirm方法是哪个)
 *          rollbackMethod:回滚方法是哪个(Cancel方法是哪个)
 */
@LocalTCC
public interface AccountTccService {
    /**
     *Try,方法,尝试执行业务功能。扣除余额
     * @param userId 用户id
     * @param money 要扣除的金额
     */
    @TwoPhaseBusinessAction(name = "deduct",commitMethod = "confirm",rollbackMethod = "cancel")
    void deduct(String userId, int money);

    /**
     * Confirm确认方法,相关于提交事务方法
     */
    void confirm();

    /**
     * Cancel取消方法,相当于回滚事务方法
     */
    void cancel();
}

编写实现业务

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第39张图片

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第40张图片


 

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第41张图片

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第42张图片

 分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第43张图片


 分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第44张图片

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第45张图片


分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第46张图片

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第47张图片

空回滚

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第48张图片

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第49张图片

 分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第50张图片

 分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第51张图片


业务悬挂

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第52张图片

 分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第53张图片

 代码

修改:TCC接口为

/*
 * 这个接口,是用于让Seata扫描,告诉Seata一些TCC相关的配置。需要
 * 1.接口上添加@LocalTCC
 * 2.在接口里定义好Try Confirm Cancel三个方法,方法名称随意
 *   需要我们使用注解@TwoPhaseBusinessAction配置一下,
 *   告诉Seata哪里是Try、哪个是Confirm、哪个是Cancel。
 *
 *   注解在Try方法上,注解要求配置
 *          name:唯一标识
 *          commitMethod:提交方法是哪个(Confirm方法是哪个)
 *          rollbackMethod:回滚方法是哪个(Cancel方法是哪个)
 */
@LocalTCC
public interface AccountTccService {
    /*
     *Try,方法,尝试执行业务功能。扣除余额
     * @param userId 用户id
     * @param money 要扣除的金额
     */
    @TwoPhaseBusinessAction(name = "deduct",commitMethod = "confirm",rollbackMethod = "cancel")
    //参数上添加@BusinessActionContextParameter注解,表示把这个参数放到Context对象里进行共享
    void deduct(@BusinessActionContextParameter(paramName = "userId") String userId,
                @BusinessActionContextParameter(paramName = "money") int money);

    /*
     * Confirm确认方法,相关于提交事务方法
     * @param context Seata提供的一个上下文对象,用于在一次全局事务整个过程中,共享数据的
     *                如果把一项数据放到这个context里,在整个事务里就能够共享着项数据
     *                这个对象里,本身就有当前事务的id
     */
    void confirm(BusinessActionContext context);
    /*
     * Cancel取消方法,相当于回滚事务方法
     */
    void cancel(BusinessActionContext context);
}

编写实现业务+@Transactional:实现幂等,要成功都成功要么反之

/*
 * 允许空回滚:Cancel方法里实现
 *      如果回滚的时候,发现冻结表里没有任何冻结信息,说明没有执行过Try
 *      这时候要回滚,就要做空回滚:记录一条冻结信息,金额是0,状态是Cancel
 *
 * 防止业务悬挂:Try方法里实现,只要执行Try成功,就一定会增加一条冻结信息
 *      已经执行Cancel回滚了,又执行Try,会造成业务悬挂
 *      我们要避免业务悬挂;如果已经有冻结记录,并且状态是Cancel说明已经回滚过了
 */
@Service
public class AccountTccServiceImpl implements AccountTccService {
    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private AccountFreezeMapper accountFreezeMapper;

    @Override
    @Transactional
    public void deduct(String userId, int money) {
        //Seata提供一个工具类,用于在Try方法里获取当前全局事务id
        String xid = RootContext.getXID();
        //要避免业务悬挂,如果已经执行Cancel方法,就不再执行Try的代码了
        AccountFreeze freeze = accountFreezeMapper.selectById(xid);
        if (freeze != null && freeze.getState() == AccountFreeze.State.CANCEL) {
            return;
        }
        //1.扣除余额
        accountMapper.deduct(userId, money);
        //2.把扣除的金额冻结起来
        freeze = new AccountFreeze();
        freeze.setXid(xid);
        freeze.setUserId(userId);
        freeze.setFreezeMoney(money);
        freeze.setState(AccountFreeze.State.TRY);
        accountFreezeMapper.insert(freeze);
    }

    @Override
    public void confirm(BusinessActionContext context) {
        //获取当前全局事务的id
        String xid = context.getXid();
        accountFreezeMapper.deleteById(xid);
    }

    @Override
    @Transactional
    public void cancel(BusinessActionContext context) {
        String xid = context.getXid();
        //1.先查询当前事务冻结的信息
        AccountFreeze freeze = accountFreezeMapper.selectById(xid);
        if (freeze == null) {
            //是没有执行try,要允许空回滚;插入一条冻结金额为0,状态是Cancel的回滚信息
            freeze = new AccountFreeze();
            freeze.setXid(xid);
            //用户id:在try方法里,使用@BusinessActionContextParameter,
            //把这个参数放到了context对象里。现在就可以从context对象里取出这个userId
            freeze.setUserId(context.getActionContext("userId").toString());
            freeze.setFreezeMoney(0);
            freeze.setState(AccountFreeze.State.CANCEL);
            accountFreezeMapper.insert(freeze);
            return;
        }
        //2.把冻结的金额加回到当前用户的余额
        accountMapper.refund(freeze.getUserId(), freeze.getFreezeMoney());
        //3.清除冻结的数据,把状态修改为Cancel,把金额设置成0
        freeze.setFreezeMoney(0);
        freeze.setState(AccountFreeze.State.CANCEL);
        accountFreezeMapper.updateById(freeze);
    }
}

    

修改Controller

让Controller调用AccountTCCServicededuct方法

@RestController
@RequestMapping("account")
public class AccountController {

    //@Autowired
    //private AccountService accountService;

    @Autowired
    private AccountTccService accountTccService;
    @PutMapping("/{userId}/{money}")
    public ResponseEntity deduct(@PathVariable("userId") String userId, @PathVariable("money") Integer money) {
        accountTccService.deduct(userId, money);
        return ResponseEntity.noContent().build();
    }
}

在全局事务入口方法上加@GlobalTransactional

在OrderServiceImpl的create方法上添加注解@GlobalTransactional

@Override
@GlobalTransactional
public Long create(Order order) {
    ......;
}

    

    

重启测试

使用Postman重新发请求进行下单,结果会下单失败;查看数据库里,订单、余额、库存数据都没变

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第54张图片

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第55张图片

4. SAGA模式

Saga 模式是 Seata 即将开源的长事务解决方案,将由蚂蚁金服主要贡献。

其理论基础是Hector & Kenneth 在1987年发表的论文Sagas。

Seata官网对于Saga的指南:Seata Saga 模式

    

原理说明

在 Saga 模式下,分布式事务内有多个参与者,每一个参与者都是一个冲正补偿服务,需要用户根据业务场景实现其正向操作和逆向回滚操作。

分布式事务执行过程中,依次执行各参与者的正向操作,如果所有正向操作均执行成功,那么分布式事务提交。如果任何一个正向操作执行失败,那么分布式事务会去退回去执行前面各参与者的逆向回滚操作,回滚已提交的参与者,使分布式事务回到初始状态。

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第56张图片

Saga也分为两个阶段:

  • 一阶段:直接提交本地事务

  • 二阶段:成功则什么都不做;失败则通过编写补偿业务来回滚

优缺点

优点:

  • 事务参与者可以基于事件驱动实现异步调用,吞吐高

  • 一阶段直接提交事务,无锁,性能好

  • 不用编写TCC中的三个阶段,实现简单

缺点:

  • 软状态持续时间不确定,时效性差

  • 没有锁,没有事务隔离,会有脏写

适用场景:

  • 业务流程长、业务流程多

  • 参与者包含其它公司或遗留系统服务,无法提供 TCC 模式要求的三个接口

5. 四种模式对比

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第57张图片

-->XA一致性最强,但性能弱

-->AT 性能好一些,但NoSQL不能参与

-->TCC 性能更好,NoSQL能参与, 但第三方系统不能参与

-->SAGA 性能更好,NoSQL能参与,第三方系统也能参与

6. 小结

1. XA模式-使用步骤
    修改所有微服务的配置文件,使用XA模式  seata.data-source-proxy-mode: XA
    修改全局事务的入口方法,添加注解@GlobalTransactional
        所有分支事务的方法,添加注解@Transactional
2. XA模式-两阶段提交过程
    一阶段:注册并执行
        开启全局事务,告诉TC
        所有分支事务注册到TC
        所有分支事务执行SQL但不提交事务
        所有分支事务向TC汇报状态
    二阶段:最终的决策结果
        TC根据所有分支事务汇报的状态做决策
        如果所有分支事务都成功:就通知所有分支执行提交操作。分支事务接收指令,执行提交
        如果任意分支事务失败了:就通知所有分支执行回滚操作。分支事务接收指令,执行回滚

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第58张图片

 分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第59张图片

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第60张图片

3. XA模式-优缺点
    优点:
        强一致性,所有节点的数据要么一起提交,要么一起回滚
        实现简单,没有代码入侵
    缺点:
        可用性弱,一阶段长时间持有数据库锁不释放,到二阶段才会释放锁,影响性能
        依赖于关系数据库本身的事务机制,NoSQL参与不进来


4. AT模式-使用步骤
    先给微服务的库里,执行SQL脚本,创建一张表,用于存储备份数据
    修改所有微服务的配置文件,设置事务模式为AT。如果不设置,默认就是AT
    修改全局事务的入口方法,添加注解@GlobalTransactional
        所有分支事务的方法,添加注解@Transactional

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第61张图片分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第62张图片分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第63张图片分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第64张图片分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第65张图片分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第66张图片分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第67张图片
5. AT模式-两阶段提交
    一阶段:注册与执行
        开启全局事务告诉TC
        各分支事务注册到TC
        各分支事务执行SQL并直接提交、备份数据
        各分支事务向TC汇报状态
    二阶段:最终的决策与处理
        TC根据所有分支事务的状态做决策
        如果任意一个分支事务失败了:会通知所有分支事务执行回滚操作。分支事务会拿备份的数据恢复过来
        如果所有分支事务都成功了:会通知所有分支事务执行提交操作。分支事务会删除备份数据
5. AT模式-脏写问题
    一个事务在一阶段直接释放DB锁,二阶段才会对数据做提交或回滚
    在一阶段和二阶段中间,其它事务可能对这条数据做修改
    
    使用“全局锁”可以解决脏写问题:
        一阶段在释放DB锁之前,先加全局锁
        二阶段在最终操作的时候,释放全局锁,添加DB锁,操作完成释放DB锁
        在一阶段和二阶段全过程,都对这条数据有锁,避免了其它事务的干扰,避免了脏写问题
6. AT模式-优缺点
    优点:
        没有代码入侵
        性能比XA模式要好:一阶段直接释放DB锁
    缺点:
        是最终一致,存储数据的临时不一致状态
        利用了框架的快照功能,会对性能造成一些影响。但是比XA模式性能要好
        依赖于关系数据库本身的事务机制,NoSQL参与不进来 


7. TCC模式-两阶段提交过程
    一阶段:注册与执行
        开启全局事务告诉TC
        各分支事务注册到TC
        各分支事务执行Try方法:执行资源的预留
        各分支事务向TC汇报状态
    二阶段:最终的决策
        TC会根据所有分支事务的状态,做最终的决策
        如果所有分支事务都成功了,就通知所有分支事务执行提交:分支事务执行Confirm方法
        如果任意分支事务失败了,就通知所有分支事务执行回滚:分支事务执行Cancel方法
8. TCC模式-业务悬挂与空回滚
    业务悬挂:已经执行过Cancel了,再执行Try。这样的话Try预留的资源将永远不会提交或回滚。要防止悬挂
    空回滚:还没有执行Try,就Cancel了。要允许空回滚
    
    防止业务悬挂,允许空回滚
        前提:
            只要执行了Try,就一定有一条冻结记录,状态是Try
            只要执行了Cancel,就一定有一条冻结记录,状态是Cancel
        实现:
            执行Try的时候,如果发现已经有冻结记录并且是Cancel,说明已经回滚过了,不再执行Try
            执行Cancel的时候,如果发现还没有冻结记录,说明还没有执行过Try,就空回滚,插入一条冻结0的状态Cancel的记录


9. TCC模式-优缺点
    优点:
        一阶段直接提交事务,不需要长时间持有DB锁,性能好
        不需要使用快照备份,而是基于资源预留的补偿操作,不需要全局锁,性能更好
        不依赖于关系数据库本身的事务机制,NoSQL也能参与进来
    缺点:
        代码入侵比较严重,需要编写Try、Confirm、Cancel方法,还要注意防悬挂、空回滚、幂等性
        是最终一致状态,存在数据的临时不一致
        不方便让老旧系统或第三方系统参与到事务里 

五、Seata高可用【拓展】

 Seata的TC服务作为分布式事务核心,一定要保证seata集群的高可用性。

1.Seata高可用架构模型

搭建TC服务集群非常简单,启动多个TC服务,注册到nacos即可,但集群并不能确保100%安全。例如集群所在机房故障了怎么办?

所以如果可用性要求较高,一般都会做异地多机房容灾。比如一个TC集群在上海,另一个TC集群在杭州:

分布式事务问题、CAP定理和BASE理论,seata入门与整合(nacos),seata的事务模式(XA模式、AT模式[重点]、TCC模式、SAGA模式、四种模式对比)、seata高可用【扩展】_第68张图片

微服务基于事务组(tx-service-group)与TC集群的映射关系,来查找当前应该使用哪个TC集群。当SH集群故障时,只需要将vgroup-mapping中的映射关系改成HZ。则所有微服务就会切换到HZ的TC集群了。

2. 实现高可用

 参考资料里《Seata高可用\seata的部署和集成.md》中的第三章节

你可能感兴趣的:(分布式,java,面试)