关于springcloud项目中使用seata所遇到的一些问题

本文主要介绍了使用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.confregistry.conf文件,这里我使用的是nacos作为注册配置中心,下面是我个人的file.confregistry.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.confregistry.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萌新,欢迎大家来进行技术交流和探讨。

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值