springboot整合seata1.4.0【完成】


一、简介

  • 本文主要介绍分布式事务框架seata(seata版本1.4.0)的安装以及springboot与seata的整合的事务回滚案例;
  • seata的官方文档路径: http://seata.io/zh-cn/
  • 本文介绍的方式是AT模式,采用的中间件是nacos,存储类型为db模式;
  • 本文默认你已会nacos的安装,如果不会请移步nacos的官方文档进行搭建;

二、seata服务端安装

2.1 seata-server服务端

2.1.1 下载seata-server服务端

  • 本文介绍的是window版本的安装;
  • 当前最新版本为1.4.0,选择binary类型的点击下载即可;
  • 下载路径: http://seata.io/zh-cn/blog/download.html ;
  • 下载下来进行解压,目录结构如下:

2.1.2 添加log文件

  • 在根目录创建logs文件夹,里面创建一个seata_gc.log的文件,结构如下:

2.2 初始化数据库

2.2.1 seata库数据表

  • 数据库名称就叫seata;

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

     

  • 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_gmt_modified_status (gmt_modified,status),
    KEY idx_transaction_id (transaction_id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

     

  • lock_table表

    CREATE TABLE lock_table (
    row_key varchar(128) NOT NULL,
    xid varchar(96) 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,
    gmt_create datetime DEFAULT NULL,
    gmt_modified datetime DEFAULT NULL,
    PRIMARY KEY (row_key),
    KEY idx_branch_id (branch_id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

     

2.2.2 业务库表

  • seata需要在每个业务库添加一张undo_log表
  • 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=utf8 COMMENT='AT transaction mode undo table';

     

2.3 修改file.conf文件

2.3.1 信息

  • 只需要修改模式为db和数据库链接信息即可,如下图:

2.3.2 修改内容

  • store.mode = db;
  • store.db.url = jdbc:mysql://ip:port/seata;
  • store.db.user = 账号
  • store.db.password = 密码

2.4 修改registry.conf文件

2.4.1 信息

  • 只需要修改注册类型和配置类型均为nacos和nacos的相关信息即可

2.4.2 修改内容

  • registry.type = nacos

  • registry.nacos.application = seata-server, 默认服务端的名称

  • registry.nacos.serverAddr = nacos服务器的8848端口地址

  • registry.nacos.group = SEATA_GROUP, 默认seata的组

  • registry.nacos.namespace = seata, 默认seata的配置在nacos的命名空间

  • registry.nacos.cluster = default, 采取默认集群即可

  • registry.nacos.username = nacos的用户名

  • registry.nacos.password = naocs的密码

  • config.type = nacos

  • config.nacos.namespace = seata, 默认seata的配置在nacos的命名空间

  • config.nacos.group = SEATA_GROUP, 默认seata的组

  • config.nacos.username = nacos的用户名

  • config.nacos.password = naocs的密码

2.5 修改context.txt文件

2.5.1 context.txt文件内容

  • 在/seata根目录下创建config.txt文件,内容如下:
    transport.type=TCP
    transport.server=NIO
    transport.heartbeat=true
    transport.enableClientBatchSendRequest=false
    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
    service.vgroupMapping.my_test_tx_group=default
    service.default.grouplist=127.0.0.1:8091
    service.enableDegrade=false
    service.disableGlobalTransaction=false
    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=false
    client.rm.tableMetaCheckerInterval=60000
    client.rm.sqlParserType=druid
    client.rm.reportSuccessEnable=false
    client.rm.sagaBranchRegisterEnable=false
    client.tm.commitRetryCount=5
    client.tm.rollbackRetryCount=5
    client.tm.defaultGlobalTransactionTimeout=60000
    client.tm.degradeCheck=false
    client.tm.degradeCheckAllowTimes=10
    client.tm.degradeCheckPeriod=2000
    store.mode=db
    store.publicKey=
    store.file.dir=file_store/data
    store.file.maxBranchSessionSize=16384
    store.file.maxGlobalSessionSize=512
    store.file.fileWriteBufferCacheSize=16384
    store.file.flushDiskMode=async
    store.file.sessionReloadReadSize=100
    store.db.datasource=druid
    store.db.dbType=mysql
    store.db.driverClassName=com.mysql.jdbc.Driver
    store.db.url=jdbc:mysql://IP:poert/seata?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.queryLimit=100
    store.db.lockTable=lock_table
    store.db.maxWait=5000
    store.redis.mode=single
    store.redis.single.host=127.0.0.1
    store.redis.single.port=6379
    store.redis.maxConn=10
    store.redis.minConn=1
    store.redis.maxTotal=100
    store.redis.database=0
    store.redis.password=
    store.redis.queryLimit=100
    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
    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
    log.exceptionRate=100
    transport.serialization=seata
    transport.compressor=none
    metrics.enabled=false
    metrics.registryType=compact
    metrics.exporterList=prometheus
    metrics.exporterPrometheusPort=9898

2.5.2 修改内容

  • service.vgroupMapping.my_test_tx_group=default
  • store.mode=db
  • store.db.url=jdbc:mysql://IP:PORT/seata?useUnicode=true&rewriteBatchedStatements=true
  • store.db.user=root
  • store.db.password=123456

2.5.3 添加nacos-config.sh文件

  • 在seata/conf目录下添加nacos-config.sh文件,内容如下:
    #!/bin/sh
    # 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.
    
    while getopts ":h:p:g:t:u:w:" opt
    do
      case $opt in
      h)
        host=$OPTARG
        ;;
      p)
        port=$OPTARG
        ;;
      g)
        group=$OPTARG
        ;;
      t)
        tenant=$OPTARG
        ;;
      u)
        username=$OPTARG
        ;;
      w)
        password=$OPTARG
        ;;
      ?)
        echo " USAGE OPTION: $0 [-h host] [-p port] [-g group] [-t tenant] [-u username] [-w password] "
        exit 1
        ;;
      esac
    done
    
    if [ -z ${host} ]; then
        host=localhost
    fi
    if [ -z ${port} ]; then
        port=8848
    fi
    if [ -z ${group} ]; then
        group="SEATA_GROUP"
    fi
    if [ -z ${tenant} ]; then
        tenant=""
    fi
    if [ -z ${username} ]; then
        username=""
    fi
    if [ -z ${password} ]; then
        password=""
    fi
    
    nacosAddr=$host:$port
    contentType="content-type:application/json;charset=UTF-8"
    
    echo "set nacosAddr=$nacosAddr"
    echo "set group=$group"
    
    urlencode() {
      length="${#1}"
      i=0
      while [ $length -gt $i ]; do
        char="${1:$i:1}"
        case $char in
        [a-zA-Z0-9.~_-]) printf $char ;;
        *) printf '%%%02X' "'$char" ;;
        esac
        i=`expr $i + 1`
      done
    }
    
    failCount=0
    tempLog=$(mktemp -u)
    function addConfig() {
      dataId=`urlencode $1`
      content=`urlencode $2`
      curl -X POST -H "${contentType}" "http://$nacosAddr/nacos/v1/cs/configs?dataId=$dataId&group=$group&content=$content&tenant=$tenant&username=$username&password=$password" >"${tempLog}" 2>/dev/null
      if [ -z $(cat "${tempLog}") ]; then
        echo " Please check the cluster status. "
        exit 1
      fi
      if [ "$(cat "${tempLog}")" == "true" ]; then
        echo "Set $1=$2 successfully "
      else
        echo "Set $1=$2 failure "
        failCount=`expr $failCount + 1`
      fi
    }
    
    count=0
    for line in $(cat $(dirname "$PWD")/config.txt | sed s/[[:space:]]//g); do
        count=`expr $count + 1`
        key=${line%%=*}
        value=${line#*=}
        addConfig "${key}" "${value}"
    done
    
    echo "========================================================================="
    echo " Complete initialization parameters,  total-count:$count ,  failure-count:$failCount "
    echo "========================================================================="
    
    if [ ${failCount} -eq 0 ]; then
        echo " Init nacos config finished, please start seata-server. "
    else
        echo " init nacos config fail. "
    fi

     

2.5.4 将context.txt文件内容上传到nacos

  • 目录结构如下:

  • 在conf文件下执行命令上传配置文件到nacos

  • 此时可以看到nacos上有对应的配置文件信息

2.6 启动服务端seata-server

2.6.1 脚本启动

  • 执行/seata/bin/seata-server.bat命令,看到如下日志即是启动成功;

  • 同时可以看到nacos上已经注册成功

四、代码整合

4.1 POM依赖

  • seata依赖
    <dependency>
      <groupId>io.seata</groupId>
      <artifactId>seata-spring-boot-starter</artifactId>
      <version>1.4.0</version>
    </dependency>

     

4.2 配置文件

  • bootstrap.yml内容如下:
    seata:
      enabled: true
      application-id: ${spring.application.name}
      enable-auto-data-source-proxy: true #是否开启数据源自动代理
      tx-service-group: my_test_tx_group #需要和config.txt上传到nacos上的service.vgroupMapping.my_test_tx_group保持一致
      service:
        vgroup-mapping:
          my_test_tx_group: default
        disable-global-transaction: false
      registry:
        type: nacos
        nacos:
          application: seata-server
          server-addr: 127.0.0.1:8848
          group: "SEATA_GROUP"
      #      namespace: "seed-local"
      config:
        type: nacos
        nacos:
          server-addr: 127.0.0.1:8848
          group: "SEATA_GROUP"
    #      namespace: "seed-local"

     

五、回滚案例

 
@GlobalTransactional(rollbackFor = Exception.class)
  public void updateTest() {
    String sql = "update tbl_card set amount=amount+1 where owner='b'";
    jdbcTemplate.update(sql);
    System.out.println(1/0);
  }

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM