「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: 7091spring:application:name: seata-serverlogging:config: classpath:logback-spring.xmlfile:path: ${log.home:${user.home}/logs/seata}extend:logstash-appender:destination: 127.0.0.1:4560kafka-appender:bootstrap-servers: 127.0.0.1:9092topic: logback_to_logstash
# 控制台访问密码
# http://localhost:7091/
console:user:username: seatapassword: seata
# seata基础配置,启动的时候需要这些配置项
seata:# 配置中心config:type: nacos # 配置中心类型为Nacosnacos: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 # 注册中心类型为Nacospreferred-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: defaultcluster:snapshot-interval: 600apply-batch: 32max-append-bufferSize: 262144max-replicator-inflight-msgs: 256disruptor-buffer-size: 16384election-timeout-ms: 1000reporter-enabled: falsereporter-initial-delay: 60serialization: jacksoncompressor: nonesync: true # 日志和快照同步到磁盘service-port: 8091 # 服务端口max-commit-retry-timeout: -1max-rollback-retry-timeout: -1rollback-retry-timeout-unlock-enable: falseenable-check-auth: trueenable-parallel-request-handle: trueenable-parallel-handle-branch: falseretry-dead-threshold: 130000xaer-nota-retry-timeout: 60000enableParallelRequestHandle: truerecovery:committing-retry-period: 1000async-committing-retry-period: 1000rollbacking-retry-period: 1000timeout-retry-period: 1000undo:log-save-days: 7log-delete-period: 86400000session:branch-async-queue-size: 5000 # 分支异步移除队列大小enable-branch-async-remove: false # 启用分支会话的异步移除# 监控配置metrics:enabled: false # 是否启用监控registry-type: compactexporter-list: prometheusexporter-prometheus-port: 9898 # Prometheus导出器端口# 传输配置transport:rpc-tc-request-timeout: 15000enable-tc-server-batch-send-response: falseshutdown:wait: 3thread-factory:boss-thread-prefix: NettyBossworker-thread-prefix: NettyServerNIOWorkerboss-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 = InnoDBDEFAULT 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 = InnoDBDEFAULT 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 = InnoDBDEFAULT 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 = InnoDBDEFAULT 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_grouptx-service-group: default_tx_group# 数据源代理模式,指定为 XA 模式data-source-proxy-mode: XA# 注册中心配置registry:# 注册中心类型为 Nacostype: nacosnacos:# 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:# 配置中心类型为 Nacostype: nacosnacos:# 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_incrementprimary 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_logunique (xid, branch_id)
)engine = InnoDBcharset = 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中的三个阶段,实现简单
缺点:
- 软状态持续时间不确定,时效性差
- 没有锁,没有事务隔离,会有脏写