文章目录
1. Seata 简介
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。1.1 四种事务模式
Seata 将为用户提供 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。- AT 模式:提供无侵入自动补偿的事务模式,详细可参考《Seata AT 模式》官方文档
- TCC 模式:支持调用自定义的提交或者回滚的逻辑,详细可参考《Seata TCC 模式》官方文档
- Saga 模式:为长事务提供有效的解决方案,详细可参考《Seata Saga 模式》官方文档
- XA 模式:强一致性事务,拥有全局事务的隔离性,详细可参考《Seata XA 模式》官方文档
1.2 三个基本组件
seata由三个基本组件构成,如下图所示:- TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,驱动全局事务提交或回滚。
- TM (Transaction Manager) - 事务管理器:定义全局事务的范围,开始全局事务、提交或回滚全局事务。
- RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
1.3 seata分布式事务的生命周期
1、TM请求TC开始一个新的全局事务,TC生成一个表示全局事务的XID。
2、XID通过微服务的调用链传播。
3、RM将本地事务注册为XID对应全局事务的分支到TC。
4、TM请求TC提交或回滚XID对应的全局事务。
5、TC驱动XID对应全局事务下的所有分支事务来完成分支提交或回滚。
2. Seata TC Server 安装
tc需要存储全局事务和分支事务的数据,目前有两种存储模式:-
file模式:适合单机部署,全局事务和分支事务的数据持久化到本地文件。
-
db模式:适合集群部署,全局事务和分支事务的数据通过db进行共享。
2.1 单机部署
打开 seata下载页面,选择最新的版本下载
# 创建seata目录
$ mkdir -p /usr/seata
$ cd /usr/seata
# 下载
$ wget https://www.github.com//seata/seata/releases/download/v1.4.0/seata-server-1.4.0.tar.gz
# 解压文件
$ tar -zxvf seata-server-1.4.0.tar.gz
# 查看seata目录
$ cd seata
$ ll
总用量 48
drwxr-xr-x. 2 root root 53 1月 19 10:21 bin # 启动TC的shell脚本
drwxr-xr-x. 3 root root 141 11月 2 17:30 conf # 配置文件
drwxr-xr-x. 3 root root 8192 11月 2 17:30 lib # 依赖的jar包
-rw-r--r--. 1 root root 11365 5月 13 2019 LICENSE
# 后台启动 tc server
$ nohup sh bin/seata-server.sh &
# 查看nohup.out日志,出现Server started表示启动成功,默认端口是8091
$ tail -f nohup.out
1:21:52.477 INFO --- [ main] io.seata.config.FileConfiguration : The file name of the operation is registry
11:21:52.486 INFO --- [ main] io.seata.config.FileConfiguration : The configuration file used is /usr/seata/seata/conf/registry.conf
11:21:53.094 INFO --- [ main] io.seata.config.FileConfiguration : The file name of the operation is file.conf
11:21:53.094 INFO --- [ main] io.seata.config.FileConfiguration : The configuration file used is file.conf
11:22:05.452 INFO --- [ main] i.s.core.rpc.netty.NettyServerBootstrap : Server started, listen port: 8091
# 再次查看seata目录,发现多了nohup.out文件和sessionStore目录
$ ll
drwxr-xr-x. 2 root root 53 1月 19 10:21 bin
drwxr-xr-x. 3 root root 141 11月 2 17:30 conf
drwxr-xr-x. 3 root root 8192 11月 2 17:30 lib
-rw-r--r--. 1 root root 11365 5月 13 2019 LICENSE
-rw-------. 1 root root 32966 1月 19 11:22 nohup.out
drwxr-xr-x. 2 root root 23 1月 19 10:26 sessionStore
# 查看sessionStore目录,file模式下持久化的文件就是 root.data
$ cd sessionStore
$ ll
-rw-r--r--. 1 root root 0 1月 19 10:26 root.data
2.2 集群部署
多个seata tc server实例组成了tc集群,它们通过db实现了全局和分支事务数据共享,则拥有了高可用的能力。每一个tc server都可以注册自己到注册中心,方便微服务应用通过注册中心获取它们的连接地址。整体架构图如下所示:
1、使用 mysql.sql 脚本初始化TC Server 数据库,脚本内容如下:
-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- the table to store GlobalSession data
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_gmt_modified_status` (`gmt_modified`, `status`),
KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
-- 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`),
KEY `idx_xid` (`xid`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(
`row_key` VARCHAR(128) NOT NULL,
`xid` VARCHAR(96),
`transaction_id` BIGINT,
`branch_id` BIGINT NOT NULL,
`resource_id` VARCHAR(256),
`table_name` VARCHAR(32),
`pk` VARCHAR(36),
`gmt_create` DATETIME,
`gmt_modified` DATETIME,
PRIMARY KEY (`row_key`),
KEY `idx_branch_id` (`branch_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
2、创建seata数据库,执行上述sql脚本,完成后的结果如下图所示:
3、修改 conf/file.conf 配置文件,设置为db模式,内容如下所示:
## transaction log store, only used in seata-server
store {
## store mode: file、db、redis
mode = "db"
## database store property
db {
## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
datasource = "druid"
## mysql/oracle/postgresql/h2/oceanbase etc.
dbType = "mysql"
driverClassName = "com.mysql.cj.jdbc.Driver"
url = "jdbc:mysql://192.168.0.118:3306/seata?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8"
user = "root"
password = "123456"
minConn = 5
maxConn = 100
globalTable = "global_table"
branchTable = "branch_table"
lockTable = "lock_table"
queryLimit = 100
maxWait = 5000
}
}
service {
vgroupMapping.my_test_tx_group = "seata-tc-server"
}
4、修改 conf/registry.conf 配置文件,设置使用Eureka注册中心,application表示TC Server 注册到eureka显示的服务名称。
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "eureka"
loadBalance = "RandomLoadBalance"
loadBalanceVirtualNodes = 10
eureka {
serviceUrl = "http://192.168.0.118:8761/eureka"
application = "seata-tc-server"
weight = "1"
}
}
5、指定端口号、节点编号启动TC Server,先后执行如下shell命令启动两个节点
# 启动第一个tc server节点
$ nohup sh bin/seata-server.sh -p 18090 -n 1 &
# 启动第二个tc server节点
$ nohup sh bin/seata-server.sh -p 28090 -n 2 &
打印 nohup.out 文件里面的日志
$ tail -f nohup.out
14:23:49.581 INFO --- [ main] io.seata.config.FileConfiguration : The file name of the operation is registry
14:23:49.623 INFO --- [ main] io.seata.config.FileConfiguration : The configuration file used is /usr/seata/seata/conf/registry.conf
14:23:52.019 INFO --- [ main] io.seata.config.FileConfiguration : The file name of the operation is file.conf
14:23:52.027 INFO --- [ main] io.seata.config.FileConfiguration : The configuration file used is file.conf
# 初始化连接池
14:24:06.970 INFO --- [ main] com.alibaba.druid.pool.DruidDataSource : {
dataSource-1} inited
# 节点启动成功
14:24:11.591 INFO --- [ main] i.s.core.rpc.netty.NettyServerBootstrap : Server started, listen port: 28090
......
# 注册中心连接成功
14:24:42.806 INFO --- [ main] com.netflix.discovery.DiscoveryClient : Discovery Client initialized at timestamp 1611037482804 with initial instances count: 1
14:24:42.807 INFO --- [ main] com.netflix.discovery.DiscoveryClient : Saw local status change event StatusChangeEvent [