分布式事务学习笔记(二)Seata架构、TC服务器部署、微服务集成Seata
文章目录
- 前言
- 2 Seata
- 2.1 Seata的架构
- 2.2 部署TC服务
- 1)下载安装包
- 2)解压
- 3)修改配置文件
- 4)在Nacos中添加TC服务配置
- 5)创建数据库表
- 6)启动TC服务
- 7)查看TC服务
- 2.3 微服务集成Seata
- 2.3.1 引入依赖
- 2.3.2 配置TC服务地址
- 2.3.3 配置其他微服务
- 2.3.3 启动微服务
前言
分布式事务学习笔记(一)分布式事务问题、CAP定理、BASE理论、Seata
2 Seata
Seata是2019年1月份蚂蚁金服和阿里巴巴共同开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。
官网地址:http://seata.io/
2.1 Seata的架构
Seata在分布式事务管理中有三个重要的角色:
- TC (Transaction Coordinator):事务协调者,维护全局和分支事务的状态,协调全局事务提交或回滚。
- TM (Transaction Manager):事务管理器,定义全局事务的范围、开始全局事务、提交或回滚全局事务。
- RM (Resource Manager):资源管理器,管理分支事务处理的资源,注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
Seata基于上述架构提供了四种不同的分布式事务解决方案:
- AT模式:最终一致的分阶段事务模式,无业务侵入,也是Seata的默认模式;
- XA模式:强一致性分阶段事务模式,牺牲了一定的可用性,无业务侵入;
- TCC模式:最终一致的分阶段事务模式,有业务侵入;
- SAGA模式:长事务模式,有业务侵入;
2.2 部署TC服务
1)下载安装包
点击官网顶部的“下载”按钮进入下载页,下载最新版本的安装包:
2)解压
3)修改配置文件
修改conf目录下的application.yml文件:
server:
port: 7091
spring:
application:
name: seata-server
logging:
config: classpath:logback-spring.xml
file:
path: ${log.home:${user.home}/logs/seata}
console:
user:
username: seata
password: seata
seata:
registry:
# TC服务的注册中心,支持: nacos, eureka, redis, zk, consul, etcd3, sofa
type: nacos
nacos:
# 注册到nacos的名称
application: seata-tc-service
server-addr: 127.0.0.1:8848
group: DEFAULT_GROUP
namespace:
username:
password:
cluster: default
config:
# 读取TC服务端的配置文件的方式,支持: nacos, consul, apollo, zk, etcd3
type: nacos
nacos:
server-addr: 127.0.0.1:8848
namespace:
group: DEFAULT_GROUP
username:
password:
# TC服务端配置文件
data-id: seataServer.properties
store:
mode: file
security:
secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
tokenValidityInMilliseconds: 1800000
ignore:
urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login,/version.json,/health,/error
4)在Nacos中添加TC服务配置
为了让TC服务集群可以共享配置,选择Nacos作为统一配置中心。因此TC服务端配置文件seataServer.properties文件需要在nacos中配好:
配置内容如下:
# 数据存储方式,db代表数据库
store.mode=db
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.jdbc.Driver
#改成自己的数据库和账密
store.db.url=jdbc:mysql://127.0.0.1:3306/jingd?useUnicode=true&rewriteBatchedStatements=true
store.db.user=root
store.db.password=1*****
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000
# 事务、日志等配置
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
# 客户端与服务端传输方式
transport.serialization=seata
transport.compressor=none
# 关闭metrics功能,提高性能
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898
5)创建数据库表
TC服务在管理分布式事务时,需要记录记全局事务、分支事务、全局锁等相关数据到数据库中,因此需要提前创建好相关表。
根据Seata官方文档,需要新建global_table表、branch_table表、lock_table表、distributed_lock表。具体的SQL在:https://gitee.com/seata-io/seata/blob/v1.5.1/script/server/db/mysql.sql
-- -------------------------------- 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_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`),
KEY `idx_xid` (`xid`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(
`row_key` VARCHAR(128) NOT NULL,
`xid` VARCHAR(128),
`transaction_id` BIGINT,
`branch_id` BIGINT NOT NULL,
`resource_id` VARCHAR(256),
`table_name` VARCHAR(32),
`pk` VARCHAR(36),
`status` TINYINT NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',
`gmt_create` DATETIME,
`gmt_modified` DATETIME,
PRIMARY KEY (`row_key`),
KEY `idx_status` (`status`),
KEY `idx_branch_id` (`branch_id`),
KEY `idx_xid_and_branch_id` (`xid` , `branch_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
CREATE TABLE IF NOT EXISTS `distributed_lock`
(
`lock_key` CHAR(20) NOT NULL,
`lock_value` VARCHAR(20) NOT NULL,
`expire` BIGINT,
primary key (`lock_key`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0);
6)启动TC服务
进入bin目录,运行seata-server.bat脚本:
报错提示找不到MySQL驱动,让加一个驱动jar到lib目录下:
Caused by: org.apache.seata.common.exception.StoreException: the {com.mysql.jdbc.Driver} can’t be found in the path E:\Program Files\apache-seata-2.1.0-incubating-bin/lib/jdbc/, please copy database driver dependencies, such as
mysql-connector-java.jar
to the path.
再次启动成功:
7)查看TC服务
在Nacos控制台可以看到TC服务已注册:
在浏览器访问http://127.0.0.1:7091
,输入账密进入TC服务控制台:
2.3 微服务集成Seata
以jd-order-service
微服务为例:
2.3.1 引入依赖
<!--seata-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<exclusions>
<!--版本较低,1.3.0,因此排除-->
<exclusion>
<artifactId>seata-spring-boot-starter</artifactId>
<groupId>io.seata</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<!--seata starter 采用1.4.2版本-->
<version>${seata.version}</version>
</dependency>
2.3.2 配置TC服务地址
在jd-order-service
微服务中的application.yml中,配置TC服务地址,通过注册中心Nacos,结合服务名称获取TC地址:
seata:
registry: # TC服务注册中心的配置,微服务根据这些信息去注册中心获取TC服务地址
type: nacos # 注册中心类型 Nacos
nacos:
server-addr: 127.0.0.1:8848
namespace: ""
group: DEFAULT_GROUP
application: seata-tc-server # Seata服务名称
username:
password:
tx-service-group: default_tx_group # 事务组名称
service:
vgroup-mapping: # 事务组与cluster的映射关系
default_tx_group: default
特别要注意的是,这里的配置和TC服务器的配置要对应起来:
2.3.3 配置其他微服务
jd-order-service
微服务和jd-order-service
微服务做相同配置。
2.3.3 启动微服务
服务启动后,通过日志可以看到TC服务成功注册到Nacos,且TM、RM注册成功:
至此,微服务整合Seata完毕,接下来就可以使用Seata来管理分布式事务了。
…
本节完,更多内容请查阅分类专栏:微服务学习笔记
感兴趣的读者还可以查阅我的另外几个专栏:
- SpringBoot源码解读与原理分析
- MyBatis3源码深度解析
- Redis从入门到精通
- MyBatisPlus详解
- SpringCloud学习笔记