Seata
一个典型的分布式事务过程?分布式事务处理过程的一ID+三组件模型?
- ,全局事务创建成功并生成一个全局唯一的 XID;
- XID 在微服务调用链路的上下文中传播;
- ,将其纳入 XID 对应全局事务的管辖;
- ;
- 。

前提条件:
- ****
- ****
- ****
************

update product set name = 'GTS' where name = 'TXC';

select id, name, since from product where name = 'TXC';
- ****
select id, name, since from product where id = 1;
{
"branchId": 641789253,
"undoItems": [{
"afterImage": {
"rows": [{
"fields": [{
"name": "id",
"type": 4,
"value": 1
}, {
"name": "name",
"type": 12,
"value": "GTS"
}, {
"name": "since",
"type": 12,
"value": "2014"
}]
}],
"tableName": "product"
},
"beforeImage": {
"rows": [{
"fields": [{
"name": "id",
"type": 4,
"value": 1
}, {
"name": "name",
"type": 12,
"value": "TXC"
}, {
"name": "since",
"type": 12,
"value": "2014"
}]
}],
"tableName": "product"
},
"sqlType": "UPDATE"
}],
"xid": "xid:xxx"
}
- ****

update product set name = 'TXC' where id = 1;

应用场景
并发比较低,适合使用seata的AT模式,解决分布式事务问题。
例如:后台管理系统的基础功能
基本定义:
********
[参考链接 TBD](http://seata.io/zh-cn/docs/overview/what-is-seata.html)********
- ****
- ****
- ****
- ****
- ****
基本定义:

- [用户文档](http://seata.io/zh-cn/docs/user/saga.html)
五、安装与测试
版本兼容
https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

数据库表
drop table if exists lock_table;
CREATE TABLE `lock_table` (
`row_key` varchar(128) NOT NULL,
`xid` varchar(128) DEFAULT NULL,
`transaction_id` bigint(20) DEFAULT NULL,
`branch_id` bigint(20) NOT NULL,
`resource_id` varchar(256) DEFAULT NULL,
`table_name` varchar(32) DEFAULT NULL,
`pk` varchar(36) DEFAULT NULL,
`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',
`gmt_create` datetime DEFAULT NULL,
`gmt_modified` datetime DEFAULT NULL,
PRIMARY KEY (`row_key`),
KEY `idx_status` (`status`),
KEY `idx_branch_id` (`branch_id`),
KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
drop table if exists global_table;
CREATE TABLE `global_table` (
`xid` varchar(128) NOT NULL,
`transaction_id` bigint(20) DEFAULT NULL,
`status` tinyint(4) NOT NULL,
`application_id` varchar(32) DEFAULT NULL,
`transaction_service_group` varchar(32) DEFAULT NULL,
`transaction_name` varchar(128) DEFAULT NULL,
`timeout` int(11) DEFAULT NULL,
`begin_time` bigint(20) DEFAULT NULL,
`application_data` varchar(2000) DEFAULT NULL,
`gmt_create` datetime DEFAULT NULL,
`gmt_modified` datetime DEFAULT NULL,
PRIMARY KEY (`xid`),
KEY `idx_status_gmt_modified` (`status`,`gmt_modified`),
KEY `idx_transaction_id` (`transaction_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
drop table if exists distributed_lock;
CREATE TABLE `distributed_lock` (
`lock_key` char(20) NOT NULL,
`lock_value` varchar(20) NOT NULL,
`expire` bigint(20) DEFAULT NULL,
PRIMARY KEY (`lock_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
drop table if exists branch_table;
CREATE TABLE `branch_table` (
`branch_id` bigint(20) NOT NULL,
`xid` varchar(128) NOT NULL,
`transaction_id` bigint(20) DEFAULT NULL,
`resource_group_id` varchar(32) DEFAULT NULL,
`resource_id` varchar(256) DEFAULT NULL,
`branch_type` varchar(8) DEFAULT NULL,
`status` tinyint(4) DEFAULT NULL,
`client_id` varchar(64) DEFAULT NULL,
`application_data` varchar(2000) DEFAULT NULL,
`gmt_create` datetime(6) DEFAULT NULL,
`gmt_modified` datetime(6) DEFAULT NULL,
PRIMARY KEY (`branch_id`),
KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
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);
drop table if exists undo_log;
CREATE TABLE `undo_log` (
`branch_id` bigint(20) NOT NULL COMMENT 'branch transaction id',
`xid` varchar(100) NOT NULL COMMENT 'global transaction id',
`context` varchar(128) NOT NULL COMMENT 'undo_log context,such as serialization',
`rollback_info` longblob NOT NULL COMMENT 'rollback info',
`log_status` int(11) NOT NULL COMMENT '0:normal status,1:defense status',
`log_created` datetime(6) NOT NULL COMMENT 'create datetime',
`log_modified` datetime(6) NOT NULL COMMENT 'modify datetime',
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='AT transaction mode undo table';
window安装启动seata
要在 Windows 上安装和启动 Seata,您可以按照以下步骤进行:
### 前置条件
1. **Java 环境**:确保已安装 JDK 8 或更高版本。
2. **数据库**:准备一个支持的数据库(如 MySQL)来存储 Seata 的事务日志。
### 步骤
#### 1. 下载 Seata
- 前往 [Seata Releases 页面](https://github.com/seata/seata/releases)下载最新的 Seata Server 压缩包。
#### 2. 解压缩
- 将下载的压缩包解压到您选择的目录,例如 `C:\seata\`.
#### 3. 配置数据库
- 创建一个数据库用于 Seata 事务日志。
- 执行 `script/server/db` 目录下的相应 SQL 脚本来初始化数据库表。
#### 4. 配置文件
- 修改 `conf/registry.conf` 和 `conf/file.conf` 文件。
**registry.conf 示例**:
```properties
registry {
type = "file"
file {
name = "file.conf"
}
}
config {
type = "file"
file {
name = "file.conf"
}
}
file.conf 示例:
service {
vgroupMapping.my_test_tx_group = "default"
default.grouplist = "127.0.0.1:8091"
}
store {
mode = "db"
db {
datasource = "druid"
dbType = "mysql"
driverClassName = "com.mysql.cj.jdbc.Driver"
url = "jdbc:mysql://localhost:3306/seata?useUnicode=true&characterEncoding=utf8&useSSL=false"
user = "your_db_user"
password = "your_db_password"
}
}
确保将 url
、user
和 password
替换为您的数据库信息。
5. 启动 Seata Server
- 打开命令提示符,导航到 Seata 目录,运行以下命令:
bin\seata-server.bat
验证
- Seata Server 启动后,您可以在控制台中查看日志输出,确保没有错误。
- 默认情况下,Seata Server 运行在
8091
端口。可以通过检查该端口是否开放来确认服务是否正常运行。
常见问题
- 端口占用:如果
8091
端口被占用,可以在file.conf
中修改port
配置。 - 数据库连接失败:确保数据库信息正确,且数据库服务正在运行。
完成以上步骤后,Seata 应该可以成功在 Windows 上运行。
## linux安装启动seata
```markdown
在 Linux 上安装和启动 Seata,可以按照以下步骤进行:
### 前置条件
1. **Java 环境**:确保已安装 JDK 8 或更高版本。
2. **数据库**:准备一个支持的数据库(如 MySQL)来存储 Seata 的事务日志。
### 步骤
#### 1. 下载 Seata
- 前往 [Seata Releases 页面](https://github.com/seata/seata/releases)下载最新的 Seata Server 压缩包。
#### 2. 解压缩
```bash
tar -zxvf seata-server-{version}.tar.gz
3. 配置数据库
- 创建一个数据库用于 Seata 事务日志。
- 执行
script/server/db
目录下的相应 SQL 脚本来初始化数据库表。
4. 配置文件
- 修改
conf/registry.conf
和conf/file.conf
文件。
registry.conf 示例:
registry {
type = "file"
file {
name = "file.conf"
}
}
config {
type = "file"
file {
name = "file.conf"
}
}
file.conf 示例:
service {
vgroupMapping.my_test_tx_group = "default"
default.grouplist = "127.0.0.1:8091"
}
store {
mode = "db"
db {
datasource = "druid"
dbType = "mysql"
driverClassName = "com.mysql.cj.jdbc.Driver"
url = "jdbc:mysql://localhost:3306/seata?useUnicode=true&characterEncoding=utf8&useSSL=false"
user = "your_db_user"
password = "your_db_password"
}
}
确保将 url
、user
和 password
替换为您的数据库信息。
5. 启动 Seata Server
- 打开终端,导航到 Seata 目录,运行以下命令:
sh bin/seata-server.sh
验证
- Seata Server 启动后,您可以在终端中查看日志输出,确保没有错误。
- 默认情况下,Seata Server 运行在
8091
端口。可以通过检查该端口是否开放来确认服务是否正常运行。
常见问题
- 端口占用:如果
8091
端口被占用,可以在file.conf
中修改port
配置。 - 数据库连接失败:确保数据库信息正确,且数据库服务正在运行。
完成以上步骤后,Seata 应该可以成功在 Linux 上运行。
```markdown
# 配置开机自启动
创建 Systemd 服务文件 创建文件 /etc/systemd/system/seata.service:
[Unit] Description=Seata Server After=network.target [Service] Type=simple User=your_user # 替换为运行服务的用户 ExecStart=/path/to/seata/bin/seata-server.sh WorkingDirectory=/path/to/seata Restart=on-failure
[Install] WantedBy=multi-user.target
将 /path/to/seata 替换为 Seata 安装目录。
# 启用并启动服务
sudo systemctl daemon-reload
sudo systemctl enable seata
sudo systemctl start seata
# 验证服务状态
sudo systemctl status seata
docker安装启动seata
https://gist.github.com/y0ngb1n/7e8f16af3242c7815e7ca2f0833d3ea6?permalink_comment_id=5080408
https://mirror.iscas.ac.cn/
https://github.com/DaoCloud/public-image-mirror
https://www.v2ex.com/t/1050454
# 可以
https://blog.csdn.net/sxf1061700625/article/details/140895299
"https://mirror.iscas.ac.cn",
"https://docker.anyhub.us.kg",
"https://dockerhub.jobcher.com",
"https://dockerhub.icu",
# 官方案例
https://seata.apache.org/zh-cn/docs/user/quickstart
在 Docker 中安装和启动 Seata,并设置自启动,可以按照以下步骤进行:
### 前置条件
1. **Docker**:确保已安装 Docker。
### 步骤
#### 1. 拉取 Seata Docker 镜像
```bash
docker pull seataio/seata-server
docker pull seataio/seata-server:1.6.1
2. 配置数据库
- 创建一个数据库用于 Seata 事务日志。
- 执行
script/server/db
目录下的相应 SQL 脚本来初始化数据库表。
3. 创建配置文件
创建 registry.conf
和 file.conf
文件,内容如下:
registry.conf 示例:
registry {
type = "file"
file {
name = "file.conf"
}
}
config {
type = "file"
file {
name = "file.conf"
}
}
file.conf 示例:
service {
vgroupMapping.my_test_tx_group = "default"
default.grouplist = "127.0.0.1:8091"
}
store {
mode = "db"
db {
datasource = "druid"
dbType = "mysql"
driverClassName = "com.mysql.cj.jdbc.Driver"
url = "jdbc:mysql://localhost:3306/seata?useUnicode=true&characterEncoding=utf8&useSSL=false"
user = "your_db_user"
password = "your_db_password"
}
}
确保将 url
、user
和 password
替换为您的数据库信息。
4. 启动 Seata Server 并设置自启动
docker run -d --name seata-server \
--restart always \
-p 8091:8091 \
-p 7091:7091 \
-v /mnt/docker/seata/resources:/seata-server/resources \
seataio/seata-server:1.6.1
docker run -d --name seata-server
--restart always
-p 8091:8091
-p 7091:7091
seataio/seata-server:1.6.1
- 将
/path/to/registry.conf
和/path/to/file.conf
替换为您本地配置文件的路径。 - Seata 默认使用以下端口:
- 8091:用于 TC (Transaction Coordinator) 服务。
- 7091:有时用于其他服务或自定义配置。
验证
- 使用
docker ps
确认容器正在运行。 - 使用
docker logs seata-server
查看日志确保没有错误。
常见问题
- 端口占用:如果
8091
端口被占用,可以在运行容器时更改端口映射。 - 数据库连接失败:确保数据库信息正确,且数据库服务正在运行。
这样,Seata Server 会在 Docker 中运行,并在服务器重启时自动启动。
### 参考链接
[https://blog.csdn.net/u013737132/article/details/133376131](https://blog.csdn.net/u013737132/article/details/133376131)
[https://blog.csdn.net/boywcx/article/details/129360049](https://blog.csdn.net/boywcx/article/details/129360049)
[https://blog.csdn.net/qq_33222798/article/details/128918225](https://blog.csdn.net/qq_33222798/article/details/128918225)
### 1、拉取seata
```sql
docker pull seataio/seata-server:1.6.1
2、挂载文件
docker run -d --name seata-server -v /mnt/docker/seata/resources:/seata-server/resources seataio/seata-server:1.6.1
docker cp seata-server:/seata-server/resources /mnt/docker/seata
docker rm -f seata-server
3、创建seata数据库
-- 创建数据库
CREATE DATABASE IF NOT EXISTS `chaoo-cds-seata`
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
-- 创建表
drop table if exists lock_table;
CREATE TABLE `lock_table` (
`row_key` varchar(128) NOT NULL,
`xid` varchar(128) DEFAULT NULL,
`transaction_id` bigint(20) DEFAULT NULL,
`branch_id` bigint(20) NOT NULL,
`resource_id` varchar(256) DEFAULT NULL,
`table_name` varchar(32) DEFAULT NULL,
`pk` varchar(36) DEFAULT NULL,
`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',
`gmt_create` datetime DEFAULT NULL,
`gmt_modified` datetime DEFAULT NULL,
PRIMARY KEY (`row_key`),
KEY `idx_status` (`status`),
KEY `idx_branch_id` (`branch_id`),
KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
drop table if exists global_table;
CREATE TABLE `global_table` (
`xid` varchar(128) NOT NULL,
`transaction_id` bigint(20) DEFAULT NULL,
`status` tinyint(4) NOT NULL,
`application_id` varchar(32) DEFAULT NULL,
`transaction_service_group` varchar(32) DEFAULT NULL,
`transaction_name` varchar(128) DEFAULT NULL,
`timeout` int(11) DEFAULT NULL,
`begin_time` bigint(20) DEFAULT NULL,
`application_data` varchar(2000) DEFAULT NULL,
`gmt_create` datetime DEFAULT NULL,
`gmt_modified` datetime DEFAULT NULL,
PRIMARY KEY (`xid`),
KEY `idx_status_gmt_modified` (`status`,`gmt_modified`),
KEY `idx_transaction_id` (`transaction_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
drop table if exists distributed_lock;
CREATE TABLE `distributed_lock` (
`lock_key` char(20) NOT NULL,
`lock_value` varchar(20) NOT NULL,
`expire` bigint(20) DEFAULT NULL,
PRIMARY KEY (`lock_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
drop table if exists branch_table;
CREATE TABLE `branch_table` (
`branch_id` bigint(20) NOT NULL,
`xid` varchar(128) NOT NULL,
`transaction_id` bigint(20) DEFAULT NULL,
`resource_group_id` varchar(32) DEFAULT NULL,
`resource_id` varchar(256) DEFAULT NULL,
`branch_type` varchar(8) DEFAULT NULL,
`status` tinyint(4) DEFAULT NULL,
`client_id` varchar(64) DEFAULT NULL,
`application_data` varchar(2000) DEFAULT NULL,
`gmt_create` datetime(6) DEFAULT NULL,
`gmt_modified` datetime(6) DEFAULT NULL,
PRIMARY KEY (`branch_id`),
KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
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);
CREATE TABLE `undo_log` (
`branch_id` bigint NOT NULL COMMENT 'branch transaction id',
`xid` varchar(100) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'global transaction id',
`context` varchar(128) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'undo_log context,such as serialization',
`rollback_info` longblob NOT NULL COMMENT 'rollback info',
`log_status` int NOT NULL COMMENT '0:normal status,1:defense status',
`log_created` datetime(6) NOT NULL COMMENT 'create datetime',
`log_modified` datetime(6) NOT NULL COMMENT 'modify datetime',
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='AT transaction mode undo table';
4、编辑seata配置文件
appliction.yml
# Copyright 1999-2019 Seata.io Group.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
server:
port: 7091
spring:
application:
name: seata-server
logging:
config: classpath:logback-spring.xml
file:
path: ${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:
config:
# support: nacos, consul, apollo, zk, etcd3
type: nacos
file:
name: file.conf
nacos:
server-addr: ip:8848
namespace: dev
group: DEFAULT_GROUP
username:
password:
context-path:
##if use MSE Nacos with auth, mutex with username/password attribute
#access-key:
#secret-key:
data-id: seata-server.properties
registry:
# support: nacos, eureka, redis, zk, consul, etcd3, sofa
type: nacos
nacos:
application: seata-server
server-addr: ip:8848
group: DEFAULT_GROUP
namespace: dev
cluster: default
username:
password:
context-path:
##if use MSE Nacos with auth, mutex with username/password attribute
#access-key:
#secret-key:
store:
# support: file 、 db 、 redis
mode: mysql
db:
datasource: druid
db-type: mysql
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://ip:端口/cloudseata?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
user: root
password: 密碼
min-conn: 10
max-conn: 100
global-table: global_table
branch-table: branch_table
lock-table: lock_table
distributed-lock-table: distributed_lock
query-limit: 1000
max-wait: 5000
# 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,/**/*.ico,/console-fe/public/**,/api/v1/auth/login
5、创建nacos集成seata配置文件
seata-server.properties
service.vgroupMapping.ruoyi-auth-group=default
service.vgroupMapping.ruoyi-system-group=default
service.vgroupMapping.ruoyi-resource-group=default
service.vgroupMapping.ruoyi-gen-group=default
service.vgroupMapping.ruoyi-job-group=default
service.enableDegrade=false
service.disableGlobalTransaction=false
# #Transaction storage configuration, only for the server. The file, DB, and redis configuration values are optional.
# store.mode=db
# store.lock.mode=db
# store.session.mode=db
# #Used for password encryption
# store.publicKey=
# #These configurations are required if the `store mode` is `db`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `db`, you can remove the configuration block.
# store.db.datasource=hikari
# store.db.dbType=mysql
# store.db.driverClassName=com.mysql.cj.jdbc.Driver
# store.db.url=jdbc:mysql://127.0.0.1:3306/ry-seata-plus?useUnicode=true&rewriteBatchedStatements=true
# store.db.user=root
# store.db.password=123456
# 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
# redis 模式 store.mode=redis 开启 (控制台查询功能有限,不影响实际执行功能)
# store.redis.host=127.0.0.1
# store.redis.port=6379
# 最大连接数
# store.redis.maxConn=10
# 最小连接数
# store.redis.minConn=1
# store.redis.database=0
# store.redis.password=
# store.redis.queryLimit=100
#Transaction rule configuration, only for the server
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.distributedLockExpireTime=10000
server.xaerNotaRetryTimeout=60000
server.session.branchAsyncQueueSize=5000
server.session.enableBranchAsyncRemove=false
#Transaction rule configuration, only for the client
client.rm.asyncCommitBufferLimit=10000
client.rm.lock.retryInterval=10
client.rm.lock.retryTimes=30
client.rm.lock.retryPolicyBranchRollbackOnConflict=true
client.rm.reportRetryCount=5
client.rm.tableMetaCheckEnable=true
client.rm.tableMetaCheckerInterval=60000
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.rm.sagaJsonParser=fastjson
client.rm.tccActionInterceptorOrder=-2147482648
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.tm.defaultGlobalTransactionTimeout=60000
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
client.tm.interceptorOrder=-2147482648
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.onlyCareUpdateColumns=true
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
client.undo.logTable=undo_log
client.undo.compress.enable=true
client.undo.compress.type=zip
client.undo.compress.threshold=64k
#For TCC transaction mode
tcc.fence.logTableName=tcc_fence_log
tcc.fence.cleanPeriod=1h
#Log rule configuration, for client and server
log.exceptionRate=100
#Metrics configuration, only for the server
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898
#For details about configuration items, see https://seata.io/zh-cn/docs/user/configurations.html
#Transport configuration, for client and server
transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableTmClientBatchSendRequest=false
transport.enableRmClientBatchSendRequest=true
transport.enableTcServerBatchSendResponse=false
transport.rpcRmRequestTimeout=30000
transport.rpcTmRequestTimeout=30000
transport.rpcTcRequestTimeout=30000
transport.threadFactory.bossThreadPrefix=NettyBoss
transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
transport.threadFactory.shareBossWorker=false
transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
transport.threadFactory.clientSelectorThreadSize=1
transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
transport.threadFactory.bossThreadSize=1
transport.threadFactory.workerThreadSize=default
transport.shutdown.wait=3
transport.serialization=seata
transport.compressor=none
6、启动seata
docker rm -f seata-server
# 參考:docker run -p 8091:8091 -p 7091:7091 --name seata-server --restart=always -e SEATA_IP=192.168.3.128 -e SEATA_PORT=8091 -v /mydata/seata/application.yml:/seata-server/resources/application.yml -v /mydata/seata/logs:/root/logs -d seataio/seata-server:1.6.1
docker run -d --name seata-server \
--restart always \
-p 8091:8091 \
-p 7091:7091 \
-e SEATA_IP=139.196.72.132 \
-e SEATA_PORT=8091 \
-v /mnt/docker/seata/resources:/seata-server/resources \
seataio/seata-server:1.6.1
7、访问seata后台
访问地址:http://ip:7091/#/login

案例测试效果
最终效果
1、扣減用户断点异常

2、订单数据库出现回滚日志

3、异常断点取消,触发分布式事务回滚,删除undo_log回滚日志

重点问题
dubbo和seata序列化问题
在 Seata 和 Dubbo 集成中,为了防止序列化不一致,可以在配置中指定序列化方式。以下是如何添加序列化配置的示例:
添加序列化配置
在你的 application.yml 中,添加 Seata 客户端的序列化配置:
yaml
复制
seata:
enabled: true
application-id: ${spring.application.name}
tx-service-group: ${spring.application.name}-group
config:
type: nacos
nacos:
server-addr: ${spring.cloud.nacos.server-addr}
group: ${spring.cloud.nacos.config.group}
namespace: ${spring.profiles.active}
data-id: seata-server.properties
registry:
type: nacos
nacos:
application: ruoyi-seata-server
server-addr: ${spring.cloud.nacos.server-addr}
group: ${spring.cloud.nacos.discovery.group}
namespace: ${spring.profiles.active}
client:
rm:
serializer: "kryo" # 或者其他兼容的序列化方式
tm:
commitRetryCount: 1
undo:
logSerialization: "jackson" # 确保 undo log 的序列化方式兼容
配置 Dubbo 序列化
在 Dubbo 的配置中,确保使用与 Seata 兼容的序列化方式:
复制
dubbo:
protocol:
name: dubbo
serialization: kryo # 确保与 Seata 使用的序列化方式一致
注意事项
一致性:确保 Seata 和 Dubbo 使用相同的序列化方式,比如 kryo 或 hessian。
可序列化:确保所有对象都实现了 Serializable 接口,并且没有不可序列化的字段。
通过以上配置,可以有效防止 Seata 和 Dubbo 之间的序列化不一致问题。
关于 Kryo 和 Hessian 的优缺点:
Kryo
优点:
高效性能:序列化和反序列化速度快。
压缩率高:生成的字节码较小。
缺点:
兼容性问题:版本升级可能导致兼容性问题。
需要手动注册类:为了获得最佳性能,通常需要手动注册序列化类。
Hessian
优点:
跨语言支持:支持多种语言的序列化和反序列化。
稳定性:对版本变化的兼容性较好。
缺点:
性能较低:比 Kryo 稍微慢一些。
较大字节码:序列化后的数据量较大。
默认序列化方式
Dubbo 默认:Hessian2
Seata 默认:Kryo
根据你的需求选择合适的序列化方式,确保在性能和兼容性之间找到平衡。
如果引入 dubbo-filter-seata 后仍然遇到序列化问题,可以尝试以下解决方案:
解决方案
统一序列化方式 确保 Dubbo 和 Seata 使用相同的序列化方式,例如 kryo 或 hessian。在配置文件中统一设置:
dts
复制
dubbo:
protocol:
name: dubbo
serialization: kryo # 或 hessian
seata:
client:
rm:
serializer: kryo # 或 hessian
检查可序列化对象 确保所有参与序列化的对象都实现了 Serializable 接口,并且没有不可序列化的字段。
手动注册类 如果使用 Kryo,手动注册需要序列化的类可以提高兼容性和性能。
版本兼容 确认 Dubbo、Seata、Kryo/Hessian 版本的兼容性,确保没有已知的序列化问题。
日志检查 查看详细的日志信息,定位具体的序列化错误原因。
通过这些步骤,可以更好地解决序列化不一致的问题。如果问题依然存在,可以考虑在社区或 GitHub 上查找类似问题的解决方案。
<dependencies>
<dependency>
<groupId>org.apache.dubbo.extensions</groupId>
<artifactId>dubbo-filter-seata</artifactId>
<version>1.0.1</version>
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- SpringBoot Seata -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.dubbo.extensions</groupId>
<artifactId>dubbo-filter-seata</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
引入 dubbo-filter-seata 依赖是为了在 Dubbo 中集成 Seata,从而支持分布式事务管理。
作用
事务拦截器:dubbo-filter-seata 提供了一个过滤器,可以自动拦截 Dubbo 服务的调用,将其纳入 Seata 的全局事务管理。
事务传播:在分布式系统中,确保不同微服务间的事务能够正确传播和管理。
注意事项
版本兼容:确保 Dubbo 和 Seata 的版本兼容,避免由于版本不匹配导致的问题。
排除依赖:你排除了 seata-core,可能是为了避免冲突或者使用项目中已有的 Seata 版本。确保项目中有正确的 seata-core 依赖。
通过这种方式,你可以将 Dubbo 服务无缝集成到 Seata 的分布式事务中。