目录
前置环境
本文中关于客户端用到的相关组件版本如下:
<java.version>17</java.version>
<spring.boot.version>3.2.4</spring.boot.version>
<spring.cloud.version>2023.0.1</spring.cloud.version>
<alibaba.cloud.version>2023.0.1.0</alibaba.cloud.version>
其他组件版本:
Seata版本:2.0
Nacos版本:2.3.2
Mysql版本:8.0.27
分布式事务
分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。
在分布式事务中,有全局事务和分支事务之分:
- 全局事务:整个分布式事务。
- 分支事务:分布式事务中包含的每个子系统中的事务。
基于CAP定理和BASE理论,衍生出两种解决分布式事务的思想:
- 最终一致:各分支事务各自提交,如果有不一致的情况,再想办法恢复数据。
- 强一致:各分支事务执行完不要提交,等待彼此结果,然后再统一提交或回滚。
Seata
Seata是什么
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式事务解决方案。
核心概念
Seata 分TC、TM和RM三个角色,TC作为服务端单独服务端部署,TM和RM作为客户端由业务系统集成。
- TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,驱动全局事务提交或回滚。
- TM (Transaction Manager) - 事务管理器:定义全局事务的范围:开始全局事务、提交或回滚全局事务。
- RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
Seata提供了四种不同的分布式事务解决方案:
- XA模式:强一致性分阶段事务模式,牺牲了一定的可用性,无业务侵入,存在严重的资源独占和阻塞问题,对系统性能有较大影响。
- TCC模式:最终一致性的分阶段事务模式,有业务侵入,需要业务方在 try、confirm、cancel 三个阶段进行编程,实现资源的预留、确认提交和回滚。
- AT模式:Seata默认模式,最终一致性的分阶段事务模式,无业务侵入,一阶段直接提交事务,减少了事务的锁定时间,提高了性能。
- SAGA模式:长事务模式,有业务侵入,适合跨多个服务的事务处理。
部署TC服务
Seata TC 端需要一个地方存储事务的数据,因此需要配置存储模式,存储模式现有 file、db、redis、raft 四种,默认是 file 模式。
file 模式为单机模式,全局事务会话信息内存中读写并异步(默认)持久化本地文件 root.data,性能较高;db 模式为高可用模式,全局事务会话信息通过db共享,相应性能差些;redis 模式 Seata-Server 1.3 及以上版本支持,性能较高,存在事务信息丢失风险,需要提前配置合适当前场景的 redis 持久化配置;raft 模式是通过封装无法高可用的 file 模式,利用 Raft 算法实现多个TC之间数据的同步;
Seata 本质上也是一个服务,因此需要配置注册中心和配置中心,Seata 支持包括 nacos 的多种配置中心,具体可以查看官方文档。
本文的TC部署统一使用 Docker 进行部署,存储模式使用 db,数据库使用 mysql,注册中心和配置中心都使用 nacos,部署步骤如下:
-
首先启动一个临时容器,将 resources 目录文件拷出的来
docker run -d -p 8091:8091 -p 7091:7091 --name seata-serve seataio/seata-server:2.0.0 docker cp seata-serve:/seata-server/resources /User/seata/config
-
数据库执行以下命令见表,不同数据库的数据库表可以参考官方Github
CREATE TABLE IF NOT EXISTS `global_table` ( `xid` VARCHAR(128) NOT NULL, `transaction_id` BIGINT, `status` TINYINT NOT NULL, `application_id` VARCHAR(32), `transaction_service_group` VARCHAR(32), `transaction_name` VARCHAR(128), `timeout` INT, `begin_time` BIGINT, `application_data` VARCHAR(2000), `gmt_create` DATETIME, `gmt_modified` DATETIME, PRIMARY KEY (`xid`), KEY `idx_status_gmt_modified` (`status`, `gmt_modified`), KEY `idx_transaction_id` (`transaction_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; -- the table to store BranchSession data CREATE TABLE IF NOT EXISTS `branch_table` ( `branch_id` BIGINT NOT NULL, `xid` VARCHAR(128) NOT NULL, `transaction_id` BIGINT, `resource_group_id` VARCHAR(32), `resource_id` VARCHAR(256), `branch_type` VARCHAR(8), `status` TINYINT, `client_id` VARCHAR(64), `application_data` VARCHAR(2000), `gmt_create` DATETIME(6), `gmt_modified` DATETIME(6), PRIMARY KEY (`branch_id`),