「seata」分布式事务seata部署及应用
- seata 版本
- 一、部署seata服务
- 1、配置config.txt文件中的属性值
- 2、为seata服务单独创建一个nacos命名空间
- 3、利用脚本上传配置文件到nacos
- 4、配置seata服务的application.yml
- 6、执行数据库脚本
- 5、使用脚本启动seata服务
- 二、配置并启动微服务
- 1、配置每个微服务的application.yml文件
- 2、在每个微服务所在的数据库执行undo_log数据表结构
- 3、启动微服务向seata注册分支事务
- 三、模式解读
- XA和AT的区别
- 1、XA模式
- 1.1 XA模式
- 两阶段
- 1.2 XA架构模型
- 1.3 XA的优缺点
- 2、AT模式
- 1.1 AT模式
- 两阶段
- 1.2 AT架构模型
- 1.3 执行流程
- 3、TCC模式
- 优缺点
- 4、SAGA模式
- 优缺点
seata 版本
seata-server-2.0.0
一、部署seata服务
1、配置config.txt文件中的属性值
目录:seata-server-2.0.0\seata\script\config-center
修改的存储事务在数据库中
事务路由规则配置,仅针对客户端(重点和难点)
# 默认配置就行
service.vgroupMapping.default_tx_group=default
store.mode=db
store.lock.mode=db
store.session.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/seata?useUnicode=true&rewriteBatchedStatements=true
# 修改数据库用户名和密码
store.db.user=root
store.db.password=root123
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.distributedLockTable=distributed_lock
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000
2、为seata服务单独创建一个nacos命名空间
命名空间名称:seata
命名空间ID:52b44c99-80b8-4902-8335-e1bf177e37ec
配置数:0 / 200
描述:分布式事务
3、利用脚本上传配置文件到nacos
前提条件:需要安装好git环境或者可以执行sh命令的运行环境
脚本目录:seata-server-2.0.0\seata\script\config-center\nacos
在窗口处执行命令:
sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 52b44c99-80b8-4902-8335-e1bf177e37ec -u nacos -w nacos
执行过程:
导入成功:
允许nacos界面如图所示(成功导入了118个配置项):
4、配置seata服务的application.yml
所在目录:seata-server-2.0.0\seata\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}
extend:
logstash-appender:
destination: 127.0.0.1:4560
kafka-appender:
bootstrap-servers: 127.0.0.1:9092
topic: logback_to_logstash
# 控制台访问密码
# http://localhost:7091/
console:
user:
username: seata
password: seata
# seata基础配置,启动的时候需要这些配置项
seata:
# 配置中心
config:
type: nacos # 配置中心类型为Nacos
nacos:
server-addr: 127.0.0.1:8848 # Nacos服务器地址
group: SEATA_GROUP # 配置文件所属的分组
username: nacos # Nacos用户名
password: nacos # Nacos密码
namespace: 52b44c99-80b8-4902-8335-e1bf177e37ec # Nacos命名空间
# 注册中心
registry:
type: nacos # 注册中心类型为Nacos
preferred-networks: 10.10.* # 首选网络
nacos:
application: seata-server # 应用名称
server-addr: 127.0.0.1:8848 # Nacos服务器地址
group: SEATA_GROUP # 配置文件所属的分组
username: nacos # Nacos用户名
password: nacos # Nacos密码
namespace: 52b44c99-80b8-4902-8335-e1bf177e37ec # Nacos命名空间
# Seata服务器配置
server:
raft:
group: default
cluster:
snapshot-interval: 600
apply-batch: 32
max-append-bufferSize: 262144
max-replicator-inflight-msgs: 256
disruptor-buffer-size: 16384
election-timeout-ms: 1000
reporter-enabled: false
reporter-initial-delay: 60
serialization: jackson
compressor: none
sync: true # 日志和快照同步到磁盘
service-port: 8091 # 服务端口
max-commit-retry-timeout: -1
max-rollback-retry-timeout: -1
rollback-retry-timeout-unlock-enable: false
enable-check-auth: true
enable-parallel-request-handle: true
enable-parallel-handle-branch: false
retry-dead-threshold: 130000
xaer-nota-retry-timeout: 60000
enableParallelRequestHandle: true
recovery:
committing-retry-period: 1000
async-committing-retry-period: 1000
rollbacking-retry-period: 1000
timeout-retry-period: 1000
undo:
log-save-days: 7
log-delete-period: 86400000
session:
branch-async-queue-size: 5000 # 分支异步移除队列大小
enable-branch-async-remove: false # 启用分支会话的异步移除
# 监控配置
metrics:
enabled: false # 是否启用监控
registry-type: compact
exporter-list: prometheus
exporter-prometheus-port: 9898 # Prometheus导出器端口
# 传输配置
transport:
rpc-tc-request-timeout: 15000
enable-tc-server-batch-send-response: false
shutdown:
wait: 3
thread-factory:
boss-thread-prefix: NettyBoss
worker-thread-prefix: NettyServerNIOWorker
boss-thread-size: 1
# 安全配置
security:
secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017 # 密钥
tokenValidityInMilliseconds: 1800000 # 令牌有效期(毫秒)
ignore:
urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login,/metadata/v1/** # 忽略的URL列表
6、执行数据库脚本
脚本所在目录:seata-server-2.0.0\seata\script\server\db
全局事务会话信息由3块内容构成,全局事务-->分支事务-->全局锁,对应表global_table、branch_table、lock_table
seata服务的完整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(1000),
`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` (`xid`)
) 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);
5、使用脚本启动seata服务
脚本所在目录:seata-server-2.0.0\seata\bin\seata-server.bat
二、配置并启动微服务
1、配置每个微服务的application.yml文件
一共有三个微服务,执行逻辑是:
- 创建新订单
- 扣减商品库存
- 从用户账户余额扣除金额
在三个微服务的application.yml文件中配置如下内容:
# 启用 Seata 分布式事务功能
seata:
enabled: true
# 启用自动数据源代理模式
enable-auto-data-source-proxy: true
# 事务组名称,用于标识相同应用下的不同事务服务,默认为 default_tx_group
tx-service-group: default_tx_group
# 数据源代理模式,指定为 XA 模式
data-source-proxy-mode: XA
# 注册中心配置
registry:
# 注册中心类型为 Nacos
type: nacos
nacos:
# Nacos 服务器地址
server-addr: 127.0.0.1:8848
# Nacos 配置文件所属的分组
group: SEATA_GROUP
# 注册到 Nacos 的应用名称
application: seata-server
# Nacos 用户名
username: nacos
# Nacos 密码
password: nacos
# Nacos 命名空间
namespace: 52b44c99-80b8-4902-8335-e1bf177e37ec
# 配置中心配置
config:
# 配置中心类型为 Nacos
type: nacos
nacos:
# Nacos 服务器地址
server-addr: 127.0.0.1:8848
# Nacos 用户名
username: nacos
# Nacos 密码
password: nacos
# Nacos 配置文件所属的分组
group: SEATA_GROUP
# Nacos 命名空间
namespace: 52b44c99-80b8-4902-8335-e1bf177e37ec
2、在每个微服务所在的数据库执行undo_log数据表结构
在每个微服务所在的数据库执行下面的回滚日志的SQL脚本
-- auto-generated definition
create table undo_log
(
id bigint auto_increment
primary key,
branch_id bigint not null,
xid varchar(100) not null,
context varchar(128) not null,
rollback_info longblob not null,
log_status int not null,
log_created datetime not null,
log_modified datetime not null,
ext varchar(100) null,
constraint ux_undo_log
unique (xid, branch_id)
)
engine = InnoDB
charset = utf8;
3、启动微服务向seata注册分支事务
三个微服务都启动之后会向seata服务注册分支事务,如下图所示:
三、模式解读
XA和AT的区别
简述AT模式与XA模式最大的区别是什么?
- XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源。
- XA模式依赖数据库机制实现回滚;AT模式利用数据快照实现数据回滚。
- XA模式强一致;AT模式最终一致
执行逻辑代码如下:
他们之间的区别可以打断点查看,一个会立即提交事务一个不会。
1、XA模式
1.1 XA模式
XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准,XA 规范
描述了全局的TM与局部的RM之间的接口,几乎所有主流的数据库都对 XA 规范 提供了支持。
两阶段
XA是规范,目前主流数据库都实现了这种规范,实现的原理都是基于两阶段提交。
正常情况:
异常情况:
一阶段:
- 事务协调者通知每个事物参与者执行本地事务
- 本地事务执行完成后报告事务执行状态给事务协调者,此时事务不提交,继续持有数据库锁
二阶段:
- 事务协调者基于一阶段的报告来判断下一步操作
- 如果一阶段都成功,则通知所有事务参与者,提交事务
- 如果一阶段任意一个参与者失败,则通知所有事务参与者回滚事务
1.2 XA架构模型
Seata对原始的XA模式做了简单的封装和改造,以适应自己的事务模型,基本架构如图:
RM一阶段的工作:
① 注册分支事务到TC
② 执行分支业务sql但不提交
③ 报告执行状态到TC
TC二阶段的工作:
-
TC检测各分支事务执行状态
a.如果都成功,通知所有RM提交事务
b.如果有失败,通知所有RM回滚事务
RM二阶段的工作:
- 接收TC指令,提交或回滚事务
1.3 XA的优缺点
XA模式的优点是什么?
- 事务的强一致性,满足ACID原则。
- 常用数据库都支持,实现简单,并且没有代码侵入
XA模式的缺点是什么?
- 因为一阶段需要锁定数据库资源,等待二阶段结束才释放,性能较差
- 依赖关系型数据库实现事务
2、AT模式
1.1 AT模式
AT模式同样是分阶段提交的事务模型,不过弥补了XA模型中资源锁定周期过长的缺陷。
两阶段
阶段一RM的工作:
- 注册分支事务
- 记录undo-log(数据快照)
- 执行业务sql并提交
- 报告事务状态
阶段二提交时RM的工作:
- 删除undo-log即可
阶段二回滚时RM的工作:
- 根据undo-log恢复数据到更新前
1.2 AT架构模型
1.3 执行流程
AT模式下,当前分支事务执行流程如下:
一阶段:
1)TM发起并注册全局事务到TC
2)TM调用分支事务
3)分支事务准备执行业务SQL
4)RM拦截业务SQL,根据where条件查询原始数据,形成快照。
5)RM执行业务SQL,提交本地事务,释放数据库锁。此时 money = 90
6)RM报告本地事务状态给TC
二阶段:
1)TM通知TC事务结束
2)TC检查分支事务状态
a)如果都成功,则立即删除快照
b)如果有分支事务失败,需要回滚。读取快照数据({"id": 1, "money": 100}
),将快照恢复到数据库。此时数据库再次恢复为100
流程图:
3、TCC模式
TCC和SAGA不做详细介绍
优缺点
TCC模式的每个阶段是做什么的?
- Try:资源检查和预留
- Confirm:业务执行和提交
- Cancel:预留资源的释放
TCC的优点是什么?
- 一阶段完成直接提交事务,释放数据库资源,性能好
- 相比AT模型,无需生成快照,无需使用全局锁,性能最强
- 不依赖数据库事务,而是依赖补偿操作,可以用于非事务型数据库
TCC的缺点是什么?
- 有代码侵入,需要人为编写try、Confirm和Cancel接口,太麻烦
- 软状态,事务是最终一致
- 需要考虑Confirm和Cancel的失败情况,做好幂等处理
4、SAGA模式
TCC和SAGA不做详细介绍
优缺点
优点:
- 事务参与者可以基于事件驱动实现异步调用,吞吐高
- 一阶段直接提交事务,无锁,性能好
- 不用编写TCC中的三个阶段,实现简单
缺点:
- 软状态持续时间不确定,时效性差
- 没有锁,没有事务隔离,会有脏写