前言
在网络上,关于Spring Cloud和Ruoyi-Cloud整合Seata的教程有很多,针对不同版本的 Seata 也有不少相关教程。
事实上,无论是 Spring Cloud 还是 Ruoyi-Cloud,其整合 Seata 的原理基本相同。这篇博文将详细介绍如何在本地开发环境下,在Ruoyi-Cloud
中实现Seata 2.0
的整合,希望能为大家在分布式项目中实现 Seata 的整合提供实用的帮助,提供一个清晰的操作思路。
一. 环境准备
- Nacos:https://nacos.io/download/nacos-server/
- Seata
[v2.0]
:https://seata.apache.org/zh-cn/unversioned/download/seata-server - Ruoyi-Cloud:https://gitee.com/y_project/RuoYi-Cloud
二、操作流程
1.并将项目配置项导入nacos中
2.导入所需要的数据库
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for branch_table
-- ----------------------------
DROP TABLE IF EXISTS `branch_table`;
CREATE TABLE `branch_table` (
`branch_id` bigint NOT NULL,
`xid` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`transaction_id` bigint NULL DEFAULT NULL,
`resource_group_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`resource_id` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`branch_type` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`status` tinyint NULL DEFAULT NULL,
`client_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`application_data` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`gmt_create` datetime(6) NULL DEFAULT NULL,
`gmt_modified` datetime(6) NULL DEFAULT NULL,
PRIMARY KEY (`branch_id`) USING BTREE,
INDEX `idx_xid`(`xid` ASC) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of branch_table
-- ----------------------------
-- ----------------------------
-- Table structure for distributed_lock
-- ----------------------------
DROP TABLE IF EXISTS `distributed_lock`;
CREATE TABLE `distributed_lock` (
`lock_key` char(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`lock_value` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`expire` bigint NULL DEFAULT NULL,
PRIMARY KEY (`lock_key`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of distributed_lock
-- ----------------------------
INSERT INTO `distributed_lock` VALUES ('AsyncCommitting', ' ', 0);
INSERT INTO `distributed_lock` VALUES ('RetryCommitting', ' ', 0);
INSERT INTO `distributed_lock` VALUES ('RetryRollbacking', ' ', 0);
INSERT INTO `distributed_lock` VALUES ('TxTimeoutCheck', ' ', 0);
-- ----------------------------
-- Table structure for global_table
-- ----------------------------
DROP TABLE IF EXISTS `global_table`;
CREATE TABLE `global_table` (
`xid` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`transaction_id` bigint NULL DEFAULT NULL,
`status` tinyint NOT NULL,
`application_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`transaction_service_group` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`transaction_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`timeout` int NULL DEFAULT NULL,
`begin_time` bigint NULL DEFAULT NULL,
`application_data` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`gmt_create` datetime NULL DEFAULT NULL,
`gmt_modified` datetime NULL DEFAULT NULL,
PRIMARY KEY (`xid`) USING BTREE,
INDEX `idx_status_gmt_modified`(`status` ASC, `gmt_modified` ASC) USING BTREE,
INDEX `idx_transaction_id`(`transaction_id` ASC) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of global_table
-- ----------------------------
-- ----------------------------
-- Table structure for lock_table
-- ----------------------------
DROP TABLE IF EXISTS `lock_table`;
CREATE TABLE `lock_table` (
`row_key` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`xid` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`transaction_id` bigint NULL DEFAULT NULL,
`branch_id` bigint NOT NULL,
`resource_id` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`table_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`pk` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`status` tinyint NOT NULL DEFAULT 0 COMMENT '0:locked ,1:rollbacking',
`gmt_create` datetime NULL DEFAULT NULL,
`gmt_modified` datetime NULL DEFAULT NULL,
PRIMARY KEY (`row_key`) USING BTREE,
INDEX `idx_status`(`status` ASC) USING BTREE,
INDEX `idx_branch_id`(`branch_id` ASC) USING BTREE,
INDEX `idx_xid`(`xid` ASC) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of lock_table
-- ----------------------------
-- ----------------------------
-- Table structure for undo_log
-- ----------------------------
DROP TABLE IF EXISTS `undo_log`;
CREATE TABLE `undo_log` (
`id` bigint NOT NULL AUTO_INCREMENT,
`branch_id` bigint NOT NULL,
`xid` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,
`context` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci 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) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `ux_undo_log`(`xid` ASC, `branch_id` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 38 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of undo_log
-- ----------------------------
SET FOREIGN_KEY_CHECKS = 1;
3.在Nacos中创建,分布式事务命名空间,并在命名空间下创建
ruoyiSeata.properties
配置文件【并指定job模块和system模块需要进行分布式事务】
# 数据存储方式,db代表数据库
store.mode=db
store.db.datasource=druid
store.db.dbType=mysql
## mysql 5.xx
## driverClassName = "com.mysql.jdbc.Driver"
## mysql 8.0
driverClassName = "com.mysql.cj.jdbc.Driver"
# 对应导入的数据库
store.db.url=jdbc:mysql://xx.xx.xx.xx:3306/seate?useUnicode=true&rewriteBatchedStatements=true&useSSL=false
store.db.user=xxx
store.db.password=xxx
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.distributedLockTable=distributed_lock
# 对应 ${spring.application.name}-group,指定需要分布式事务的模块
service.vgroupMapping.ruoyi-job-group=default
service.vgroupMapping.ruoyi-system-group=default
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
配置结果如下:
4.配置seata
打开解压的seata文件目录,找到conf/application.yml
文件,并打开编辑
server:
port: 7091
spring:
application:
name: ruoyiSeata-server # 这是一个Spring Boot应用程序,当前应用的名称为 ruoyiSeata-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
console:
user:
username: seata
password: seata
seata:
# 指定 Seata 事务服务的组名为 my-tx-group。
# 这在分布式事务中用来标识一组全局事务,各个微服务在参与分布式事务时,会使用这个组名来注册并加入到同一个事务协调中
# 自定义:可以是任何你希望的字符串,包括随机生成的字符串
tx-service-group: my-tx-group
config:
type: nacos
nacos:
server-addr: xx.xx.xx.xx:8848 # 对应nacos地址
context-path: /nacos # 如果不使用代理(如nginx)可不写,后续解释
data-id: ruoyiSeata.properties # 对应【分布式事务命名空间 ruoyi_seata】下创建ruoyiSeata.properties配置文件
namespace: d10a9eb9-82b9-4c06-b8f4-9aa46a5aff4a # 对应分布式事务命名空间
registry:
type: nacos
nacos:
application: ruoyiSeata-server
server-addr: xx.xx.xx.xx:8848 # 对应nacos地址
cluster: default
context-path: /nacos # 如果不使用代理(如nginx)可不写,后续解释
namespace: d10a9eb9-82b9-4c06-b8f4-9aa46a5aff4a # 对应分布式事务命名空间
store:
mode: file
#server:
#service-port: 8091 #If not configured, the default is '${server.port} + 1000'
security:
secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
tokenValidityInMilliseconds: 1800000
ignore:
urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login
context-path: /nacos说明
Nginx 配置:
upstream nacos_servers {
server nacos-server-1:8848;
server nacos-server-2:8848;
}
server {
listen 80;
location /nacos/ {
proxy_pass http://nacos_servers/nacos/;
}
}
请求路径:
客户端发出的请求路径为 http://nginx-server/nacos/v1/cs/configs。
Nginx 将此请求转发为 http://nacos-server-1:8848/nacos/v1/cs/configs,Nacos 接收到的是正确的路径,因为它配置了上下文路径 /nacos。
如果没有设置上下文路径,而 Nginx 将请求的路径多加了一层 /nacos,会因为找不到对应的 API 而报错。
打开解压的seata文件目录,进入bin
文件夹,双击seata-server.bat
启动seata服务
5.需要使用分布式事务的模块引入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
5.配置需要分布式事务的模块
[job、system]
,对应内容可以放在nacos配置文件
中,也可以写在bootstrap.yml
中
job模块添加seata配置
seata:
enabled: true
application-id: ruoyi-job
# Seata 事务组编号,用于 TC 集群名
tx-service-group: ruoyi-job-group
service:
vgroup-mapping:
ruoyi-job-group: default
config:
type: nacos
nacos:
server-addr: xx.xx.xx.xx:8848 # 对应nacos地址
group: DEFAULT_GROUP
data-id: ruoyiSeata.properties # 对应【分布式事务命名空间 ruoyi_seata】下创建ruoyiSeata.properties配置文件
namespace: d10a9eb9-82b9-4c06-b8f4-9aa46a5aff4a # 对应分布式事务命名空间
registry:
type: nacos
nacos:
application: ruoyiSeata-server # 对应`conf/application.yml`中registry.nacos.application
server-addr: xx.xx.xx.xx:8848 # 对应nacos地址
cluster: default
group: DEFAULT_GROUP
namespace: d10a9eb9-82b9-4c06-b8f4-9aa46a5aff4a # 对应分布式事务命名空间
system模块添加seata配置
seata:
enabled: true
application-id: ruoyi-system
# Seata 事务组编号,用于 TC 集群名
tx-service-group: ruoyi-system-group
service:
vgroup-mapping:
ruoyi-system-group: default
config:
type: nacos
nacos:
server-addr: xx.xx.xx.xx:8848 # 对应nacos地址
group: DEFAULT_GROUP
data-id: ruoyiSeata.properties # 对应【分布式事务命名空间 ruoyi_seata】下创建ruoyiSeata.properties配置文件
namespace: d10a9eb9-82b9-4c06-b8f4-9aa46a5aff4a # 对应分布式事务命名空间
registry:
type: nacos
nacos:
application: ruoyiSeata-server # 对应`conf/application.yml`中registry.nacos.application
server-addr: xx.xx.xx.xx:8848 # 对应nacos地址
cluster: default
group: DEFAULT_GROUP
namespace: d10a9eb9-82b9-4c06-b8f4-9aa46a5aff4a # 对应分布式事务命名空间
6.使用时,在对应的方法名上追加注解
@GlobalTransactional(rollbackFor = Exception.class)
,即可实现分布式事务
例如:@GlobalTransactional(rollbackFor = Exception.class) public void aa() { SysUser sysUser = new SysUser(); sysUser.setDeptId(105L); sysUser.setUserName("aa"); sysUser.setPassword("aa"); sysUser.setNickName("aa"); // 远程调用,修改数据库 AjaxResult ajaxResult = remoteUserService.insertUser(sysUser); throw new RuntimeException("报错了"); }
在抛出异常后,远程调用的操作同样会进行回滚