Seata知识汇总和Springboot整合


目录

  1. Seata概述
  2. Springboot+ShardingJDBC+Seata整合

参考文档

Seata概述

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。官网地址Seata

Seata工作流程

Seata 定义了 3 个核心组件:

  • TC(Transaction Coordinator):事务协调器,它是事务的协调者(这里指的是 Seata 服务器),主要负责维护全局事务和分支事务的状态,驱动全局事务提交或回滚。
  • TM(Transaction Manager):事务管理器,它是事务的发起者,负责定义全局事务的范围,并根据 TC 维护的全局事务和分支事务状态,做出开始事务、提交事务、回滚事务的决议。
  • RM(Resource Manager):资源管理器,它是资源的管理者(这里可以将其理解为各服务使用的数据库)。它负责管理分支事务上的资源,向 TC 注册分支事务,汇报分支事务状态,驱动分支事务的提交或回滚。以上三个组件相互协作,TC 以 Seata 服务器(Server)形式独立部署,TM 和 RM 则是以 Seata Client 的形式集成在微服务中运行,其整体工作流程如下图。

Seata 的整体工作流程如下:

  1. TM 向 TC 申请开启一个全局事务,全局事务创建成功后,TC 会针对这个全局事务生成一个全局唯一的 XID;
  2. XID 通过服务的调用链传递到其他服务;
  3. RM 向 TC 注册一个分支事务,并将其纳入 XID 对应全局事务的管辖;
  4. TM 根据 TC 收集的各个分支事务的执行结果,向 TC 发起全局事务提交或回滚决议;
  5. TC 调度 XID 下管辖的所有分支事务完成提交或回滚操作。

Seata工作模式

Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式

AT模式

前提

  • 基于支持本地 ACID 事务的关系型数据库。

  • Java 应用,通过 JDBC 访问数据库。

  • 创建undo_log表记录事务

    -- 注意此处0.3.0+ 增加唯一索引 ux_undo_log
    CREATE TABLE `undo_log` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `branch_id` bigint(20) NOT NULL,
      `xid` varchar(100) NOT NULL,
      `context` varchar(128) NOT NULL,
      `rollback_info` longblob NOT NULL,
      `log_status` int(11) NOT NULL,
      `log_created` datetime NOT NULL,
      `log_modified` datetime NOT NULL,
      `ext` varchar(100) DEFAULT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

整体机制

两阶段提交协议的演变:

  • 一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
  • 二阶段:
    • 提交异步化,非常快速地完成。
    • 回滚通过一阶段的回滚日志进行反向补偿。

整体流程

以一个示例来说明整个 AT 分支的工作过程。

业务表:product

Field Type Key
id bigint(20) PRI
name varchar(100)
since varchar(100)

AT 分支事务的业务逻辑:

update product set name = 'GTS' where name = 'TXC';

一阶段

过程:

  1. 解析 SQL:得到 SQL 的类型(UPDATE),表(product),条件(where name = ‘TXC’)等相关的信息。
  2. 查询前镜像:根据解析得到的条件信息,生成查询语句,定位数据。
select id, name, since from product where name = 'TXC';

得到前镜像:

id name since
1 TXC 2014
  1. 执行业务 SQL:更新这条记录的 name 为 ‘GTS’。
  2. 查询后镜像:根据前镜像的结果,通过 主键 定位数据。
select id, name, since from product where id = 1;

得到后镜像:

id name since
1 GTS 2014
  1. 插入回滚日志:把前后镜像数据以及业务 SQL 相关的信息组成一条回滚日志记录,插入到 UNDO_LOG 表中。
{
	"branchId": 641789253,
	"undoItems": [{
		"afterImage": {
			"rows": [{
				"fields": [{
					"name": "id",
					"type": 4,
					"value": 1
				}, {
					"name": "name",
					"type": 12,
					"value": "GTS"
				}, {
					"name": "since",
					"type": 12,
					"value": "2014"
				}]
			}],
			"tableName": "product"
		},
		"beforeImage": {
			"rows": [{
				"fields": [{
					"name": "id",
					"type": 4,
					"value": 1
				}, {
					"name": "name",
					"type": 12,
					"value": "TXC"
				}, {
					"name": "since",
					"type": 12,
					"value": "2014"
				}]
			}],
			"tableName": "product"
		},
		"sqlType": "UPDATE"
	}],
	"xid": "xid:xxx"
}
  1. 提交前,向 TC 注册分支:申请 product 表中,主键值等于 1 的记录的 全局锁
  2. 本地事务提交:业务数据的更新和前面步骤中生成的 UNDO LOG 一并提交。
  3. 将本地事务提交的结果上报给 TC。

二阶段-回滚

  1. 收到 TC 的分支回滚请求,开启一个本地事务,执行如下操作。
  2. 通过 XID 和 Branch ID 查找到相应的 UNDO LOG 记录。
  3. 数据校验:拿 UNDO LOG 中的后镜与当前数据进行比较,如果有不同,说明数据被当前全局事务之外的动作做了修改。这种情况,需要根据配置策略来做处理,详细的说明在另外的文档中介绍。
  4. 根据 UNDO LOG 中的前镜像和业务 SQL 的相关信息生成并执行回滚的语句:
update product set name = 'TXC' where id = 1;
  1. 提交本地事务。并把本地事务的执行结果(即分支事务回滚的结果)上报给 TC。

二阶段-提交

  1. 收到 TC 的分支提交请求,把请求放入一个异步任务的队列中,马上返回提交成功的结果给 TC。
  2. 异步任务阶段的分支提交请求将异步和批量地删除相应 UNDO LOG 记录。

TCC模式

一个分布式的全局事务,整体是 两阶段提交 的模型。全局事务是由若干分支事务组成的,分支事务要满足 两阶段提交 的模型要求,即需要每个分支事务都具备自己的:

  • 一阶段 prepare 行为
  • 二阶段 commit 或 rollback 行为

根据两阶段行为模式的不同,我们将分支事务划分为 Automatic (Branch) Transaction ModeManual (Branch) Transaction Mode.

AT 模式基于 支持本地 ACID 事务关系型数据库

  • 一阶段 prepare 行为:在本地事务中,一并提交业务数据更新和相应回滚日志记录。
  • 二阶段 commit 行为:马上成功结束,自动 异步批量清理回滚日志。
  • 二阶段 rollback 行为:通过回滚日志,自动 生成补偿操作,完成数据回滚。

相应的,TCC 模式,不依赖于底层数据资源的事务支持:

  • 一阶段 prepare 行为:调用 自定义 的 prepare 逻辑。
  • 二阶段 commit 行为:调用 自定义 的 commit 逻辑。
  • 二阶段 rollback 行为:调用 自定义 的 rollback 逻辑。

所谓 TCC 模式,是指支持把 自定义 的分支事务纳入到全局事务的管理中。

Saga模式

Saga模式是SEATA提供的长事务解决方案,在Saga模式中,业务流程中每个参与者都提交本地事务,当出现某一个参与者失败则补偿前面已经成功的参与者,一阶段正向服务和二阶段补偿服务都由业务开发实现。

Saga模式示意图

理论基础:Hector & Kenneth 发表论⽂ Sagas (1987)

适用场景

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

优势

  • 一阶段提交本地事务,无锁,高性能
  • 事件驱动架构,参与者可异步执行,高吞吐
  • 补偿服务易于实现

缺点

Seata配置中心

  • 什么是配置中心?配置中心可以说是一个”大货仓”,内部放置着各种配置文件,你可以通过自己所需进行获取配置加载到对应的客户端.比如Seata Client端(TM,RM),Seata Server(TC),会去读取全局事务开关,事务会话存储模式等信息.
  • Seata的配置中心与Spring cloud的配置中心区别是?在广义上来说,并无区别,只不过Spring cloud的配置中心仅是作用于它们自身的组件,而Seata的配置中心也是一样是作用于Seata自身.(注:Spring cloud的配置中心与Seata无关)
  • Seata支持哪些配置中心?
    1. nacos
    2. consul
    3. apollo
    4. etcd
    5. zookeeper
    6. file (读本地文件, 包含conf、properties、yml配置文件的支持)

Seata注册中心

  • 什么是注册中心?注册中心可以说是微服务架构中的”通讯录“,它记录了服务和服务地址的映射关系。在分布式架构中,服务会注册到这里,当服务需要调用其它服务时,就到这里找到服务的地址,进行调用.比如Seata Client端(TM,RM),发现Seata Server(TC)集群的地址,彼此通信.
  • Seata的注册中心与Dubbo,Spring cloud的注册中心区别是?在广义上来说,并无区别,只不过Dubbo与Spring cloud的注册中心仅是作用于它们自身的组件,而Seata的注册中心也是一样是作用于Seata自身.(注:Dubbo与Spring cloud的注册中心与Seata无关)
  • Seata支持哪些注册中心?
    1. eureka
    2. consul
    3. nacos
    4. etcd
    5. zookeeper
    6. sofa
    7. redis
    8. file (直连)

Seata安装

Seata分TC、TM和RM三个角色,TC(Server端)为单独服务端部署,TM和RM(Client端)由业务系统集成。

Server端存储模式

Server端存储模式(store.mode)现有file、db、redis三种(后续将引入raft,mongodb)

  • file模式无需改动,直接启动即可。 file模式为单机模式,全局事务会话信息内存中读写并持久化本地文件root.data,性能较高;

  • db模式为高可用模式,全局事务会话信息通过db共享,相应性能差些;

  • redis模式Seata-Server 1.3及以上版本支持,性能较高,存在事务信息丢失风险,请提前配置合适当前场景的redis持久化

部署

这是使用Nacos作为配置中心和注册中心

  • 先启动Nacos,访问http://127.0.0.1:8848可以看见控制台

  • https://github.com/seata/seata/releases,下载服务器软件包,将其解压缩。

  • 上传配置信息到nacos

    • 在解压缩后的seata/script/config-center目录找到这两个文件config.txtnacos-config.sh

    • nacos-config.sh文件复制到seata/conf目录,把config.txt复制到seata目录

    • 修改config.txt文件,主要是加上后续需要使用的事物分组service.vgroupMapping.service-order-group=default

      有多个事务分组就加多个(在下面建立工程的时候,还会来修改和重新推送一遍配置)

      后续在工程的application.yml文件会配置如下配置:

      spring:

      ​ alibaba:

      ​ seata:

      ​ tx-service-group: service-order-group #事务分组名

    • seata/conf目录下运行命令sh nacos-config.sh -h localhost -p 8848 -t 21bdae91-3386-4cb8-9b24-e7778eda2956 -u nacos -w nacos上传配置到nacos

      命令各参数说明如下:

      • -h:Nacos 的 host,默认取值为 localhost
      • -p:端口号,默认取值为 8848
      • -t :命名空间ID
      • -g:Nacos 配置的分组,默认取值为 SEATA_GROUP
      • -u:Nacos 用户名
      • -w:Nacos 密码

      这里有几个上传失败,是在配置里面值为空,问题不大

    • 在nacos新建命名空间,并新建名为seata.properties的data id配置,Group为SEATA_GROUP,内容为上述config.txt内容

    • 刷新nacos控制台,可以看见新增的配置

  • 进入conf目录,参考application.example.yml修改配置文件application.yml,gourp、namespace、data-id配置和上述配置中心一致,连接nacos

  • 启动Seata服务

参数 全写 作用 备注
-h –host 指定在注册中心注册的 IP 不指定时获取当前的 IP,外部访问部署在云环境和容器中的 server 建议指定
-p –port 指定 server 启动的端口 默认为 8091
-m –storeMode 事务日志存储方式 支持file,db,redis,默认为 file 注:redis需seata-server 1.3版本及以上
-n –serverNode 用于指定seata-server节点ID 1,2,3…, 默认为 1
-e –seataEnv 指定 seata-server 运行环境 dev, test 等, 服务启动时会使用 registry-dev.conf 这样的配置

本地启动时如下

$ sh seata-server.sh -p 8091 -h 127.0.0.1 -m file

可以访问http://127.0.0.1:7091/地址看到Seata的控制台,用户和密码都是seata

  • 在nacos控制台对应的命名空间下看到seata服务

  • 关闭Seata服务

    由于shell脚本启动了后台运行,关闭流程如下:

    ps -ef|grep seata  --> 找到对应的PID
    kill -9 PID --> 关闭seata进程

Springboot+ShardingJDBC+Seata整合

使用Nacos作为配置中心和注册中心

依赖


文章作者: 小小千千
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 小小千千 !
评论
  目录