0%

seata接入SpringBoot项目流程汇总+问题总结

本文都是在项目部署都是基于windos

1 Seata

1.1 Seata 模式简介

AT模式

​ 如果不熟悉(就是我)分布式相关解决模式的相关知识,可以看一个b站的视频,从76P开始讲Seata的,有助于更加了解Seata的机制。

1.2 Seata配置

​ ①下载 + 解压(推荐一直都在用的BandZip)

​ ②初始化数据库(创建名为seata的数据库并运行下面的sql文件,创建seata运行所需要的三张表)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
-- -------------------------------- 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_gmt_modified_status` (`gmt_modified`, `status`),
KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;

-- 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 = utf8;

-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(
`row_key` VARCHAR(128) NOT NULL,
`xid` VARCHAR(96),
`transaction_id` BIGINT,
`branch_id` BIGINT NOT NULL,
`resource_id` VARCHAR(256),
`table_name` VARCHAR(32),
`pk` VARCHAR(36),
`gmt_create` DATETIME,
`gmt_modified` DATETIME,
PRIMARY KEY (`row_key`),
KEY `idx_branch_id` (`branch_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;

​ ②修改配置文件

​ 进入seata\config目录,如果要使用集群模式,需要修改:file.config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

store {
## 修改模式,改为db
mode = "db"

file {
dir = "sessionStore"
maxBranchSessionSize = 16384
maxGlobalSessionSize = 512
fileWriteBufferCacheSize = 16384
sessionReloadReadSize = 100
flushDiskMode = async
}
db {
datasource = "druid"
dbType = "mysql"
driverClassName = "com.mysql.jdbc.Driver"
## 修改数据库连接(连接到第一部配置的seata数据库)的配置,url、user、password
url = "jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true"
user = "root"
password = "Qwer;t592665"
minConn = 5
maxConn = 30
globalTable = "global_table"
branchTable = "branch_table"
lockTable = "lock_table"
queryLimit = 100
maxWait = 5000
}
}

​ ③设置nacos为注册中心

​ 进入seata\config目录,修改:registry.config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
registry {
#注册为nacos
type = "nacos"

nacos {
application = "seata-server"
serverAddr = "localhost:8848"
namespace = "public"
cluster = "default"
username = ""
password = ""
}
file {
name = "file.conf"
}
}

config {
##修改为nacos配置
type = "nacos"

nacos {
serverAddr = "localhost"
namespace = "public"
group = "SEATA_GROUP"
username = ""
password = ""
}
file {
name = "file.conf"
}
}

​ ④启动Seata

​ 1.在RELEASE页面下载相应版本并解压

​ 2.直接启动

​ 在 Linux/Mac 下

1
$ sh ./bin/seata-server.sh

​ 在 Windows 下

1
.\seata-server.bat

接下来我们部署Nacos作为Seata的配置中心

2 Nacos

2.1Nacos部署

​ ①在nacos下载页面中下载,我下载时最新版本为1.3.0

​ ②创建数据库nacos以及相应的表(在conf目录下有sql文件)

1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE TABLE seata_order.undo_log
(
id BIGINT(20) NOT NULL AUTO_INCREMENT,
branch_id BIGINT(20) NOT NULL,
xid VARCHAR(100) NOT NULL,
context VARCHAR(128) NOT NULL,
rollback_info LONGBLOB NOT NULL,
log_status INT(11) NOT NULL,
log_created DATETIME NOT NULL,
log_modified DATETIME NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY ux_undo_log (xid, branch_id)
) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8;

​ ③配置数据库连接信息

​ 在nacos\conf目录下找到application.properties 配置文件,增加MySQL配置:

1
2
3
4
5
6
7
8
9
10
11
12

#*************** Config Module Related Configurations ***************#
### If user MySQL as datasource:
spring.datasource.platform=mysql

### Count of DB:
db.num=1

### Connect URL of DB:
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user=root
db.password=******

​ ③启动Nacos服务

​ windows就是startup.cmd(linux就是startup.sh)。

​ ④打开 http://127.0.0.1:8848/nacos 地址,使用默认的用户「nacos/nacos」进行登陆。

​ 这样我们就算部署成功了。

3 SpringBoot相关配置

​ 可以参照芋道的内容。

​ ①设置分支事务回滚表undo_log

​ 项目中每个数据库都要设置相应的undo_log表用于分支事务的回滚。

1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE TABLE seata_order.undo_log
(
id BIGINT(20) NOT NULL AUTO_INCREMENT,
branch_id BIGINT(20) NOT NULL,
xid VARCHAR(100) NOT NULL,
context VARCHAR(128) NOT NULL,
rollback_info LONGBLOB NOT NULL,
log_status INT(11) NOT NULL,
log_created DATETIME NOT NULL,
log_modified DATETIME NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY ux_undo_log (xid, branch_id)
) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8;

​ ②引入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- 实现对 Seata 的自动化配置 -->
<dependency>
<groupId>io.seata</group Id>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.2.0</version>
</dependency>

<!-- 实现 Nacos 作为配置中心的自动化配置 -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.4</version>
</dependency>

<!-- 实现对 dynamic-datasource 的自动化配置 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>

​ ③配置文件

​ 修改application.yaml,没有就创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
server:
port: 8081 # 端口
servlet:
context-path: /parking

spring:
application:
name: parking # 应用名

datasource:
# dynamic-datasource-spring-boot-starter 动态数据源的配配项,对应 DynamicDataSourceProperties 类
dynamic:
primary: all-ds # 设置默认的数据源或者数据源组,默认值即为 master
datasource:
# 系统总数据源配置
all-ds:
url: jdbc:mysql://127.0.0.1:3306/parking_lot?useSSL=false&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.jdbc.Driver
username: root
password: Qwer;t592665
# 系统支数据源 swpu配置
swpu-ds:
url: jdbc:mysql://127.0.0.1:3306/parking_lot_swpu?useSSL=false&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.jdbc.Driver
username: root
password: Qwer;t592665
seata: true # 是否启动对 Seata的集成

# Seata 配置项,对应 SeataProperties类
seata:
application-id: ${spring.application.name} # Seata 应用编号,默认为 ${spring.application.name}
tx-service-group: ${spring.application.name}-group # Seata 事务组编号,用于 TC 集群名
# 服务配置项,对应 ServiceProperties 类
service:
# 虚拟组和分组的映射
vgroup-mapping:
parking-group: default ##⭐⭐注意这里的parking-group要和上面的应用名称的一致,不然会报错:no available service 'null' found, please make sure registry config correct
# 分组和 Seata 服务的映射
grouplist:
default: 127.0.0.1:8091

​ ④项目实例可以参考芋道的文章。

​ ⑤总结一下我遇到的问题:

1:no available service ‘null’ found, please make sure registry config correct

​ 因为我开始参考的是别人的项目,有些细节没弄清楚,看了一下github大家的issue,突然想到seata的事务组名称(也就是vgroup mapping下面第一个配置项目的key)这里必须设置为:你的项目名称+-group,我这里就是parking-group。

2:RM register failed

​ 主要原因是我的GlobalTransaction没有管理到 到Transactional,导致这事务之间没有联系一起