一、介绍
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
Seata分TC、TM和RM三个角色,TC(Server端)为单独服务端部署,TM和RM(Client端)由业务系统集成。
概念:
TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,驱动全局事务提交或回滚。
TM (Transaction Manager) - 事务管理器:定义全局事务的范围:开始全局事务、提交或回滚全局事务。
RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
二、服务端
用Nacos作为seata的注册中心和配置中心
1. Nacos下载安装及配置
1.1 Nacos下载安装
Nacos下载地址:https://github.com/alibaba/nacos/releases
解压 nacos-server-2.3.0.zip,创建nacos需要的数据库,并使用\nacos-server-2.3.0\nacos\conf\mysql-schema.sql 初始化表。
修改\nacos-server-2.3.0\nacos\conf\application.properties,打开以下配置的注释
修改\nacos-server-2.3.0\nacos\bin\startup.cmd 为单机模式运行
双击 startup.cmd 启动Nacos
浏览器输入:http://localhost:8848/nacos/
nacos2.3.0默认没有开启鉴权,如要开启,请看https://nacos.io/zh-cn/docs/v2/guide/user/auth.html
1.2 新建一个命名空间 seata_demo
新增命名空间后,在配置列表中就可以看到seata_demo这个tab
2.下载和配置Seata Server端(TC:事务协调者)
https://github.com/seata/seata/releases
目前(2024-1-27)最新版本为2.0.0
2.1 创建seata数据库
- 创建名为“seata”的数据库
- 执行数据库脚本:..\seata-server-2.0.0\seata\script\server\db\mysql.sql
2.2 修改配置信息
解压后,打开文件 ..\seata-server-2.0.0\seata\conf\application.yml
- 修改配置中心类型:“seata.config.type”的值修改为nacos,并增加nacos地址信息
- 修改注册中心类型:“seata.registry.type”的值修改为nacos,并增加nacos地址信息
- 修改事务会话信息存储方式:“seata.store.mode”的值修改为db
注,“seata.store.mode”说明:
file模式为单机模式,全局事务会话信息内存中读写并持久化本地文件root.data,性能较高;
db模式为高可用模式,全局事务会话信息通过db共享,相应性能差些;
redis模式,性能较高,但存在事务信息丢失风险,请提前配置合适当前场景的redis持久化配置.
详细参数说明见:参数配置 | Apache Seata
2.3 导入配置信息到Nacos配置中心
使用https://github.com/apache/incubator-seata/tree/develop/script/config-center 的config.txt文件,并根据自己需要适当修改。
把文件https://github.com/apache/incubator-seata/blob/develop/script/config-center/config.txt 拷贝到目录“D:\projects\seata-server-2.0.0\seata”下;文件 https://github.com/apache/incubator-seata/blob/develop/script/config-center/nacos/nacos-config.sh拷贝到“\seata-server-2.0.0\seata\bin”目录下(对config.txt文件中的配置信息,如数据库信息做相应的修改,也可以在成功导入到Nacos以后通过Nacos修改)。因为是windows,所以通过GIT的命令行执行shell脚本。进入GIT安装目录双击执行“git-bash.exe”打开命令行窗口,进入到“nacos-config.sh”所在录目录,执行命令:
./nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 05efbaac-4222-4b84-9da0-c74462962098
如果nacos有密码,则后面增加“-u 用户 -w 密码”:
./nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 61fd843e-3484-4636-9216-2493013b8d05 -u 用户 -w 密码
......(省略部分信息)......
通过提示信息可以看到配置已经导入成功。刷新Nacos上的配置列表可以看到刚才导入的配置信息,如果有些配置需要调整,可以直接通过Nacos的界面操作进行修改。
2.4 启动seata server:
双击 \seata-server-2.2.0\seata\bin\seata-server.bat 启动 seata
默认用户名/密码:seata/seata
登录到Nacos上,看到seata服务已注册成功
2.5 遇到的问题
1、数据库连接url问题
Establishing SSL connection without server's identity verification is not recommended.
According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set.
For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'.
You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
解决:数据库连接url中增加“useSSL=true”
2、数据库驱动问题
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
解决:
修改store.db.driverClassName=com.mysql.jdbc.Driver 为store.db.driverClassName=com.mysql.cj.jdbc.Driver
三、客户端
Seata管理的分布式事务的典型生命周期:
(1). TM要求TC开始一项新的全局事务。TC生成代表全局事务的XID。
(2). XID通过微服务的调用链传播。
(3). RM将本地事务注册为XID到TC的相应全局事务的分支。
(4). TM要求TC提交或回退相应的XID全局事务。
(5). TC驱动XID的相应全局事务下的所有分支事务以完成分支提交或回滚。
借鉴官方的例子,通过3个微服务来演示(AT模式)。
AT模式:基于支持本地ACDI事务的关系型数据库,根据两阶段提交协议的演变,一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。二阶段:提交,或通过一阶段的回滚日志进行反向补偿。(更多信息:http://seata.io/zh-cn/docs/overview/what-is-seata.html)
三个服务:
- 仓储服务(Storage) :对给定的商品扣除仓储数量。
- 订单服务(Order) :根据采购需求创建订单。
- 帐户服务(Account):从用户帐户中扣除余额。
1. 数据库:
创建数据库:`seata_demo_account`、`seata_demo_order`、`seata_demo_storage`,并为每个库创建对应的业务表:
-- 帐户服务(Account)`seata_demo_account`库表
CREATE TABLE `account_tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` varchar(255) DEFAULT NULL,
`money` decimal(10,2) DEFAULT '0.00',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 插入测试数据
INSERT INTO account_tbl (user_id, money) VALUES ('1001', 100);
INSERT INTO account_tbl (user_id, money) VALUES ('1002', 200);
-- 订单服务(Order)`seata_demo_order`库表
CREATE TABLE `order_tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` varchar(255) DEFAULT NULL,
`commodity_code` varchar(255) DEFAULT NULL,
`count` int(11) DEFAULT '0',
`money` decimal(10,2) DEFAULT '0.00',
`cttime` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 插入测试数据
INSERT INTO storage_tbl (commodity_code, count) VALUES ('2001', 10);
-- 仓储服务(Storage) `seata_demo_storage`库表
CREATE TABLE `storage_tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`commodity_code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '商品代码',
`count` int(11) DEFAULT '0' COMMENT '商品数量',
`price` decimal(10,2) DEFAULT '1.00' COMMENT '商品单价',
`cttime` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `commodity_code` (`commodity_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
在每个业务库中都创建`undo_log`表,用于记录回滚日志,业务数据更新前,会先把记录都保存在这张表,在业务异常时根据这张表的信息进行回滚。如果是正常提交事务,提交后,undo_log表中的对应记录会被删掉。
https://github.com/apache/incubator-seata/blob/2.x/script/client/at/db/mysql.sql
-- `seata_demo_account`, `seata_demo_order`, `seata_demo_storage`业务库中分别创建`undo_log`表
CREATE TABLE IF NOT EXISTS `undo_log`
(
`branch_id` BIGINT NOT NULL COMMENT 'branch transaction id',
`xid` VARCHAR(128) NOT NULL COMMENT 'global transaction id',
`context` VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',
`rollback_info` LONGBLOB NOT NULL COMMENT 'rollback info',
`log_status` INT(11) NOT NULL COMMENT '0:normal status,1:defense status',
`log_created` DATETIME(6) NOT NULL COMMENT 'create datetime',
`log_modified` DATETIME(6) NOT NULL COMMENT 'modify datetime',
UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8mb4 COMMENT ='AT transaction mode undo table';
ALTER TABLE `undo_log` ADD INDEX `ix_log_created` (`log_created`);
2. 代码
参考的官方示例:https://github.com/apache/incubator-seata-samples
附:官方脚本说明(https://github.com/seata/seata/tree/1.4.1/script):
客户端的配置信息:https://github.com/apache/incubator-seata/tree/2.x/script/client
目录说明:
at: AT模式下的 `undo_log` 建表语句
conf: 客户端的配置文件
saga: SAGA 模式下所需表的建表语句
spring: SpringBoot 应用支持的配置文件
服务端配置信息:https://github.com/apache/incubator-seata/tree/2.x/script/server
目录说明:
db: server 侧的保存模式为 `db` 时所需表的建表语句
docker-compose: server 侧通过 docker-compose 部署的脚本
helm: server 侧通过 Helm 部署的脚本
kubernetes: server 侧通过 Kubernetes 部署的脚本