关于Alibaba seata0.9版本升级到1.3踩坑集锦
本文主要介绍了使用seata时所遇到的一些问题
事先说明:一开始我所使用的是seata0.9版本,具体教程可以参考尚硅谷周阳老师发布的视频,而我的项目中所使用的是seata1.3版本,其中seata0.9~seata1.3当中有很多的变动,具体变动请参照下文。
下载地址
注意:seata1.3中官网下载的jar包中不再提供sql语句,需要连同源码一并下载,去源码中找到sql语句执行。(本段最下方有seata下载地址)。
seata官网下载地址: https://github.com/seata/seata/releases
seata网盘下载地址:https://pan.baidu.com/s/1LHNEdxZed7-j2blRoZoQZw,提取码:wygf
目录对比
这是官方提供的,seata官网的1.3版本不再提供sql语句,并且file.conf
文件中不再有service模块。
这是本地我自己使用的整合完毕的版本。
另附上我本地使用的seata网盘下载地址:https://pan.baidu.com/s/1LHNEdxZed7-j2blRoZoQZw 提取码:wygf
创建数据库、业务库创建db_undo_log表
1.首先从源码中找到sql语句,分别是业务数据库的db_undo_log.sql、和seata库本身的db_store.sql,这里就不多做说明了,直接将我的语句代码放到这里。
seata数据库sql对应db_store.sql
/*
Navicat Premium Data Transfer
Source Server : localhost_3306
Source Server Type : MySQL
Source Server Version : 50720
Source Host : localhost:3306
Source Schema : seata
Target Server Type : MySQL
Target Server Version : 50720
File Encoding : 65001
Date: 05/03/2021 10:50:47
*/
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(20) NOT NULL,
`xid` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`transaction_id` bigint(20) NULL DEFAULT NULL,
`resource_group_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`lock_key` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`branch_type` varchar(8) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`status` tinyint(4) NULL DEFAULT NULL,
`client_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`application_data` varchar(2000) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`gmt_create` datetime(0) NULL DEFAULT NULL,
`gmt_modified` datetime(0) NULL DEFAULT NULL,
PRIMARY KEY (`branch_id`) USING BTREE,
INDEX `idx_xid`(`xid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of branch_table
-- ----------------------------
-- ----------------------------
-- Table structure for global_table
-- ----------------------------
DROP TABLE IF EXISTS `global_table`;
CREATE TABLE `global_table` (
`xid` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`transaction_id` bigint(20) NULL DEFAULT NULL,
`status` tinyint(4) NOT NULL,
`application_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`transaction_service_group` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`transaction_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`timeout` int(11) NULL DEFAULT NULL,
`begin_time` bigint(20) NULL DEFAULT NULL,
`application_data` varchar(2000) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`gmt_create` datetime(0) NULL DEFAULT NULL,
`gmt_modified` datetime(0) NULL DEFAULT NULL,
PRIMARY KEY (`xid`) USING BTREE,
INDEX `idx_gmt_modified_status`(`gmt_modified`, `status`) USING BTREE,
INDEX `idx_transaction_id`(`transaction_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin 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 utf8 COLLATE utf8_bin NOT NULL,
`xid` varchar(96) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`transaction_id` mediumtext CHARACTER SET utf8 COLLATE utf8_bin NULL,
`branch_id` mediumtext CHARACTER SET utf8 COLLATE utf8_bin NULL,
`resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`table_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`pk` varchar(36) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`gmt_create` datetime(0) NULL DEFAULT NULL,
`gmt_modified` datetime(0) NULL DEFAULT NULL,
PRIMARY KEY (`row_key`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of lock_table
-- ----------------------------
SET FOREIGN_KEY_CHECKS = 1;
业务库日志表,对应db_undo_log.sql
/*
Navicat Premium Data Transfer
Source Server : localhost_3306
Source Server Type : MySQL
Source Server Version : 50720
Source Host : localhost:3306
Source Schema : lwzx_yujing
Target Server Type : MySQL
Target Server Version : 50720
File Encoding : 65001
Date: 05/03/2021 10:50:59
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for undo_log
-- ----------------------------
DROP TABLE IF EXISTS `undo_log`;
CREATE TABLE `undo_log` (
`branch_id` bigint(20) NOT NULL COMMENT 'branch transaction id',
`xid` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'global transaction id',
`context` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci 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',
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 26 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'AT transaction mode undo table' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of undo_log
-- ----------------------------
SET FOREIGN_KEY_CHECKS = 1;
修改file.conf和registry.conf
修改seata-server-1.3.0\seata\conf目录下的file.conf
和registry.conf
文件,这里我使用的是nacos
作为注册配置中心,下面是我个人的file.conf
和registry.conf
文件代码,请参照修改。
registry.conf
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos"
nacos {
application = "seata-server"
serverAddr = "192.168.220.213:8848"
group = "SEATA_GROUP"
namespace = "4c92b6c4-35e7-4195-a039-032f69437362"
cluster = "default"
username = "nacos"
password = "nacos"
}
eureka {
serviceUrl = "http://localhost:8761/eureka"
application = "default"
weight = "1"
}
redis {
serverAddr = "localhost:6379"
db = 0
password = ""
cluster = "default"
timeout = 0
}
zk {
cluster = "default"
serverAddr = "127.0.0.1:2181"
sessionTimeout = 6000
connectTimeout = 2000
username = ""
password = ""
}
consul {
cluster = "default"
serverAddr = "127.0.0.1:8500"
}
etcd3 {
cluster = "default"
serverAddr = "http://localhost:2379"
}
sofa {
serverAddr = "127.0.0.1:9603"
application = "default"
region = "DEFAULT_ZONE"
datacenter = "DefaultDataCenter"
cluster = "default"
group = "SEATA_GROUP"
addressWaitTime = "3000"
}
file {
name = "file.conf"
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "nacos"
nacos {
serverAddr = "192.168.220.213:8848"
namespace = "4c92b6c4-35e7-4195-a039-032f69437362"
group = "SEATA_GROUP"
username = "nacos"
password = "nacos"
}
consul {
serverAddr = "127.0.0.1:8500"
}
apollo {
appId = "seata-server"
apolloMeta = "http://192.168.1.204:8801"
namespace = "application"
}
zk {
serverAddr = "127.0.0.1:2181"
sessionTimeout = 6000
connectTimeout = 2000
username = ""
password = ""
}
etcd3 {
serverAddr = "http://localhost:2379"
}
file {
name = "file.conf"
}
}
file.conf
## transaction log store, only used in seata-server
store {
## store mode: file、db、redis
mode = "db"
## file store property
file {
## store location dir
dir = "sessionStore"
# branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
maxBranchSessionSize = 16384
# globe session size , if exceeded throws exceptions
maxGlobalSessionSize = 512
# file buffer size , if exceeded allocate new buffer
fileWriteBufferCacheSize = 16384
# when recover batch read size
sessionReloadReadSize = 100
# async, sync
flushDiskMode = async
}
## database store property
db {
## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
datasource = "druid"
## mysql/oracle/postgresql/h2/oceanbase etc.
dbType = "mysql"
driverClassName = "com.mysql.jdbc.Driver"
url = "jdbc:mysql://127.0.0.1:3306/seata"
user = "root"
password = "root"
minConn = 5
maxConn = 30
globalTable = "global_table"
branchTable = "branch_table"
lockTable = "lock_table"
queryLimit = 100
maxWait = 5000
}
## redis store property
redis {
host = "127.0.0.1"
port = "6379"
password = ""
database = "0"
minConn = 1
maxConn = 10
queryLimit = 100
}
}
配置生成
在seata1.3源码中seata-1.3.0\script\config-center\nacos
目录下找到nacos-config.sh
文件,这里需要用到git-bash工具执行nacos-config.sh
脚本,将配置注册到nacos配置中心上。
我在这里是将
nacos-config.sh
复制到seata-server-1.3.0\seata\conf
目录执行的,这里需要用到config.txt文件,所以需要先修改config.txt文件。
这里将我的config.txt文件内容分享出来,其实主要是修改了数据库的用户名和密码,这里需要注意的是,service.vgroupMapping.my_test_tx_group=default
其中的 vgroupMapping
在0.9版本的配置文件中是下划线的命名vgroup_mapping
,另外在0.9版本中config.txt
名字叫做nacos-config.txt
,我的就是从0.9的版本中拉过来的。
config.txt
transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.thread-factory.boss-thread-prefix=NettyBoss
transport.thread-factory.worker-thread-prefix=NettyServerNIOWorker
transport.thread-factory.server-executor-thread-prefix=NettyServerBizHandler
transport.thread-factory.share-boss-worker=false
transport.thread-factory.client-selector-thread-prefix=NettyClientSelector
transport.thread-factory.client-selector-thread-size=1
transport.thread-factory.client-worker-thread-prefix=NettyClientWorkerThread
transport.thread-factory.boss-thread-size=1
transport.thread-factory.worker-thread-size=8
transport.shutdown.wait=3
service.vgroupMapping.my_test_tx_group=default
service.enableDegrade=false
service.disable=false
service.max.commit.retry.timeout=-1
service.max.rollback.retry.timeout=-1
client.async.commit.buffer.limit=10000
client.lock.retry.internal=10
client.lock.retry.times=30
client.lock.retry.policy.branch-rollback-on-conflict=true
client.table.meta.check.enable=true
client.report.retry.count=5
client.tm.commit.retry.count=1
client.tm.rollback.retry.count=1
store.mode=file
store.file.dir=file_store/data
store.file.max-branch-session-size=16384
store.file.max-global-session-size=512
store.file.file-write-buffer-cache-size=16384
store.file.flush-disk-mode=async
store.file.session.reload.read_size=100
store.db.datasource=dbcp
store.db.db-type=mysql
store.db.driver-class-name=com.mysql.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true
store.db.user=root
store.db.password=root
store.db.min-conn=1
store.db.max-conn=3
store.db.global.table=global_table
store.db.branch.table=branch_table
store.db.query-limit=100
store.db.lock-table=lock_table
recovery.committing-retry-period=1000
recovery.asyn-committing-retry-period=1000
recovery.rollbacking-retry-period=1000
recovery.timeout-retry-period=1000
transaction.undo.data.validation=true
transaction.undo.log.serialization=jackson
transaction.undo.log.save.days=7
transaction.undo.log.delete.period=86400000
transaction.undo.log.table=undo_log
transport.serialization=seata
transport.compressor=none
metrics.enabled=false
metrics.registry-type=compact
metrics.exporter-list=prometheus
metrics.exporter-prometheus-port=9898
support.spring.datasource.autoproxy=false
最后执行nacos-config.sh
脚本,执行成功后结果是这样的
启动seata服务
执行\seata-server-1.3.0\seata\bin
目录下的seata-server.bat脚本即可。
执行成功后可以在nacos服务列中看到seata-server服务。
到这里seata的1.3配置就完成了。
项目中的使用
项目中的maven依赖
<!--SpringCloud alibaba seata-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-seata</artifactId>
<version>2.2.0.RELEASE</version>
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</exclusion>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
<version>1.3.0</version>
</dependency>
springboot启动类中需要禁用掉springboot提供的自动注入
添加@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
这个注解即可。
由于我的项目中使用了mybatis-plus用于操作数据库的持久化工具,所以需要手动代理一下,就是上图中的@Import({DataSourceProxyConfig.class})
。
DataSourceProxyConfig.class
代码
@Configuration
public class DataSourceProxyConfig {
@Value("${mybatis-plus.mapper-locations}")
private String mapperLocations;
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource(){
return new DruidDataSource();
}
@Bean
public DataSourceProxy dataSourceProxy(DataSource dataSource) {
return new DataSourceProxy(dataSource);
}
//代理mybaits-plus
@Bean
public MybatisSqlSessionFactoryBean sqlSessionFactoryBean(DataSourceProxy dataSourceProxy) throws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSourceProxy);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());
return sqlSessionFactoryBean;
}
//代理mybatis / mybatis-config
// @Bean
// public SqlSessionFactory sqlSessionFactoryBean(DataSourceProxy dataSourceProxy) throws Exception {
// SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
// sqlSessionFactoryBean.setDataSource(dataSourceProxy);
// sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
// sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());
// return sqlSessionFactoryBean.getObject();
// }
}
YML配置
1.3版本的seata不再像0.9版本一样需要将file.conf
和registry.conf
放到项目中,可以将配置写进bootstrap.yml/application.yml文件中。
以下是我的bootstrap.yml文件,由于我的项目中使用了sentinel所以项目中有sentinel的配置,如果不需要的可以手动删除。
bootstrap.yml
server:
port: 8009
servlet:
context-path: /lwzxrest # API http://localhost:9100/swagger-ui.html
spring:
application:
name: item-model-themeTask
profiles:
active: dev
#active: test #test
#active: prod #prod
cloud:
loadbalancer:
retry:
enabled: true #开启重试机制
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
#server-addr: 192.168.220.248:8848 #test
#server-addr: xx.xx.xx.xx:8848 #prod
namespace: 4c92b6c4-35e7-4195-a039-032f69437362
#namespace: 656c9440-6312-41ae-ae8b-9f615517e9e2 #test
#namespace: 6c825231-75e0-4e50-93bd-a64ee127e813 #prod
config:
server-addr: localhost:8848 #Nacos作为配置中心地址
#server-addr: 192.168.220.248:8848 #test
#server-addr: xx.xx.xx.xx:8848 #prod
file-extension: yaml
group: DEV_GROUP
#group: TEST_GROUP #test
#group: PROD_GROUP #prod
namespace: 4c92b6c4-35e7-4195-a039-032f69437362
#namespace: 656c9440-6312-41ae-ae8b-9f615517e9e2 #test
#namespace: 6c825231-75e0-4e50-93bd-a64ee127e813 #prod
# 配置文件名称格式:${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
sentinel:
transport:
dashboard: localhost:8080 #配置Sentinel dashboard地址
#dashboard: 192.168.220.246:8080 #配置Sentinel dashboard地址
#dashboard: xx.xx.xx.xx:8080 #配置Sentinel dashboard地址
port: 8720
# filter:
# # 需要进行限流监控的接口,多个匹配用逗号隔开
# url-patterns: /sentinel/*,/api/yjjc/subject/infosubscribe
# servlet:
# block-page: /sentinel/block
datasource:
flow:
nacos:
server-addr: localhost:8848
#server-addr: 192.168.220.248:8848 #test
#server-addr: xx.xx.xx.xx:8848 #prod
dataId: ${spring.application.name}-flow
groupId: DEV_GROUP
#groupId: TEST_GROUP #test
#groupId: PROD_GROUP #prod
namespace: 4c92b6c4-35e7-4195-a039-032f69437362
#namespace: 656c9440-6312-41ae-ae8b-9f615517e9e2 #test
#namespace: 6c825231-75e0-4e50-93bd-a64ee127e813 #prod
data-type: json
rule-type: flow
management:
endpoints:
web:
exposure:
include: '*'
# 激活Sentinel对Feign的支持
feign:
sentinel:
enabled: true
seata:
enabled: true
application-id: ${spring.application.name} #你的当前服务的application name
#这里的名字与file.conf中vgroup_mapping.my_test_tx_group = "default"相同
tx-service-group: my_test_tx_group
enable-auto-data-source-proxy: true
service:
#这里的名字与file.conf中vgroup_mapping.my_test_tx_group = "default"相同
vgroup-mapping:
my_test_tx_group: default
#这里的名字与file.conf中default.grouplist = "127.0.0.1:8091"相同
grouplist:
default: 127.0.0.1:8091
config:
type: nacos
nacos:
namespace:
serverAddr: localhost:8848
#这里的名字就是registry.conf中 nacos的group名字
group: SEATA_GROUP
userName: "nacos"
password: "nacos"
registry:
type: nacos
nacos:
application: seata-server
#这里的地址就是你的nacos的地址,可以更换为线上
serverAddr: 192.168.220.213:8848
#这里的名字就是registry.conf中 nacos的group名字
group: SEATA_GROUP
namespace: 4c92b6c4-35e7-4195-a039-032f69437362
userName: "nacos"
password: "nacos"
逻辑代码使用@GlobalTransactional
注解
最后来看一下业务代码中的使用,注意@GlobalTransactional
注解使用在事务的发起者方法上即可,被调用的服务无需使用。
openfeign接口
消息接收者服务
经测试,如果出现异常,两个数据库中的数据都会进行回滚,反之则提交。
本人java新手、CSDN萌新,欢迎大家来进行技术交流和探讨。