在分布式系统中,如果一个业务需要多个服务合作完成,而且每一个服务都有事务, 多个事务必须同时成功或失败,这样的事务就是分布式事务。其中的每个服务的事务就是一个分支事务。 整个业务称为全局事务

初识Seata

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

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

分布式事务解决思路

解决分布式事务,各个子事务之间必须能感知到彼此的事务状态,才能保证状态一致。

【分布式事务】-XA模式与AT模式解决分布式事务_分布式事务

Seata架构

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

  • TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。
  • TM (Transaction Manager) - 事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务。
  • RM (Resource Manager) - 资源管理器:管理分支事务,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

【分布式事务】-XA模式与AT模式解决分布式事务_分布式事务_02

部署TC服务

准备数据库表

Seata支持多种存储模式,但考虑到持久化的需要,我们一般选择基于数据库存储。执行《seata-tc.sql》,导入数据库表:

【分布式事务】-XA模式与AT模式解决分布式事务_回滚_03

准备配置文件

【分布式事务】-XA模式与AT模式解决分布式事务_回滚_04

【分布式事务】-XA模式与AT模式解决分布式事务_分布式事务_05

我们将整个seata文件夹拷贝到虚拟机的/root目录:

Docker部署

docker run --name seata \
-p 8099:8099 \
-p 7099:7099 \
-e SEATA_IP=192.168.21.129 \
-v ./seata:/seata-server/resources \
--privileged=true \
--network hm-net \
-d \
seataio/seata-server:1.5.2

【分布式事务】-XA模式与AT模式解决分布式事务_全局事务_06

【分布式事务】-XA模式与AT模式解决分布式事务_回滚_07

微服务集成Seata

首先,要引入Seata依赖:

<!--统一配置管理-->
  <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  </dependency>
  <!--读取bootstrap文件-->
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-bootstrap</artifactId>
  </dependency>
  <!--seata-->
  <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
  </dependency>

改造配置

首先在nacos上添加一个共享的seata配置,命名为shared-seata.yaml

seata:
  registry: # TC服务注册中心的配置,微服务根据这些信息去注册中心获取tc服务地址
    type: nacos # 注册中心类型 nacos
    nacos:
      server-addr: 192.168.21.129:8848 # nacos地址
      namespace: "" # namespace,默认为空
      group: DEFAULT_GROUP # 分组,默认是DEFAULT_GROUP
      application: seata-server # seata服务名称
      username: nacos
      password: nacos
  tx-service-group: hmall # 事务组名称
  service:
    vgroup-mapping: # 事务组与tc集群的映射关系
      hmall: "default"

【分布式事务】-XA模式与AT模式解决分布式事务_分布式事务_08

然后,在application.yml中添加配置,让微服务找到TC服务地址

【分布式事务】-XA模式与AT模式解决分布式事务_回滚_09

【分布式事务】-XA模式与AT模式解决分布式事务_全局事务_10

XA模式

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

【分布式事务】-XA模式与AT模式解决分布式事务_回滚_11

一阶段:

①RM注册分支事务到TC

②RM执行分支业务sq|但不提交

③RM报告执行状态到TC

二阶段:

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

a.如果都成功,通知所有RM提交事务

b.如果有失败,通知所有RM回滚事务

RM接收TC指令,提交或回滚事务

优点

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

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

缺点

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

●依赖关系型数据库实现事务

实现

Seata的starter已经完成了XA模式的自动装配,实现非常简单,步骤如下:

1.修改application.yml文件 ( 每个参与事务的微服务),开启XA模式:

【分布式事务】-XA模式与AT模式解决分布式事务_全局事务_12

【分布式事务】-XA模式与AT模式解决分布式事务_回滚_13

2.给发起全 局事务的入口方法添加@GlobalTransactional注解,本例中是OrderServicelmpl中的create方法:

【分布式事务】-XA模式与AT模式解决分布式事务_回滚_14

【分布式事务】-XA模式与AT模式解决分布式事务_分布式事务_15

AT模式

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

阶段一RM的工作:

●注册分支事务

●记录undo-log ( 数据快照)

●执行业务sql并提交

●报告事务状态

阶段二提交时RM的工作:

  • 删除undo-log即可

阶段二回滚时RM的工作:

  • 根据undo-log恢复数据到更新前

【分布式事务】-XA模式与AT模式解决分布式事务_全局事务_16

实现

首先添加一张表到数据库中

【分布式事务】-XA模式与AT模式解决分布式事务_分布式事务_17

注意:是每个数据库增加这张表

【分布式事务】-XA模式与AT模式解决分布式事务_回滚_18

然后修改yml文件,将事务模式改为AT模式:

【分布式事务】-XA模式与AT模式解决分布式事务_分布式事务_19

AT模式与XA模式最大的区别

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

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

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