分布式事务seata1.4.2使用配置

简介

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
我们项目中使用AT模式,AT模式分为两个阶段:
一阶段:
业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
二阶段:
提交异步化,非常快速地完成。
回滚通过一阶段的回滚日志进行反向补偿。

1. 开启seata事务的工程中引入相关依赖

pom.xml中引入seata的jar包,1.4.2之前的版本,都不支持一个data id的方式存放所有的seata服务器配置信息,从1.4.2后支持一个配置文件的方式,所以此处排除默认引入的1.3的包,需引入1.4.2。

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    <exclusions>
        <!-- 要与seata服务端版本一直,所以把自带的替换掉 -->
        <exclusion>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!--使用1.4.2版本,对配置可以使用data-id一个配置文件包含其他所有的配置信息-->
<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>${seata.version}</version>
</dependency>

关于spring cloud alibaba生态的版本参考地址:https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

2. seata server服务器搭建

服务器下载地址:https://github.com/seata/seata/releases,对下载的工程进行解压、配置。
配置的模板文件下载地址:https://github.com/seata/seata/tree/1.4.2/script

(1)seata/conf/file.conf

此配置项为seata 服务器的存储配置,存储方式选择db,再配置数据库的连接信息,以及处理事务的全局性表(表名使用默认的就可以)。

store {
  ## store mode: file、db、redis
  mode = "db"
  ## rsa decryption public key
  publicKey = ""
 
  ## database store property
  db {
    ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
    datasource = "druid"
    ## datasource = "dbcp"
    ## mysql/oracle/postgresql/h2/oceanbase etc.
    dbType = "mysql"
    ## mysql 5.xx
    ## driverClassName = "com.mysql.jdbc.Driver"
    ## mysql 8.0
    driverClassName = "com.mysql.cj.jdbc.Driver"
    ## if using mysql to store the data, recommend add rewriteBatchedStatements=true in jdbc connection param
    url = "jdbc:mysql://ip:port/umapp_appcenter?rewriteBatchedStatements=true"
    ## url = "jdbc:mysql://ip:port/umapp_appcenter?useUnicode=true&characterEncoding=utf-8&useSSL=false&nullCatalogMeansCurrent=true&serverTimezone=Asia/Shanghai"
    user = "appcenter"
    password = "123456"
    minConn = 5
    maxConn = 100
    globalTable = "global_table"
    branchTable = "branch_table"
    lockTable = "lock_table"
    queryLimit = 100
    maxWait = 5000
  }
}

注意点:
driverClassName驱动的配置需要根据mysql的版本决定:
mysql5.+使用 driverClassName = "com.mysql.jdbc.Driver"
mysql8使用 driverClassName = "com.mysql.cj.jdbc.Driver"

(2)seata/conf/registry.conf

需要配置选用的注册中心类型(nacos),注册中心的连接信息;配置中心的类型,配置中心的连接信息。

registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "nacos"
 
  nacos {
    application = "seata-server"
    serverAddr = "127.0.0.1:7500"
    group = "SEATA_GROUP"
    namespace = "public"
    cluster = "default"
    username = "nacos"
    password = "nacos"
  }
}
 
config {
  # file、nacos 、apollo、zk、consul、etcd3
  type = "nacos"
 
  nacos {
    serverAddr = "127.0.0.1:7500"
    namespace = "public"
    group = "SEATA_GROUP"
    username = "nacos"
    password = "nacos"
    dataId = "seataServer.properties"
  }
}

注意点:

①当nacos开启安全配置(在nacos的conf/application.properties中配置nacos.core.auth.enabled=true)后,对nacos的连接信息都要带上用户名、密码等信息

②在seata1.4.2后才可以使用dataId = "seataServer.properties"的方式读取配置信息

(3)script/config-center/config.txt:

此配置信息是seata事务的相关属性,在nacos中创建data id 时,粘贴到文本值的内容,即seataServer.properties的配置项,seata使用1.4.2版本,新建的data id文件类型选择properties。若是使用seata1.4.2之前的版本,以下的每个配置项在nacos中就是一个条目,需要使用script/config-center/nacos/下的nacos-config.sh(linux或者windows下装git)或者nacos-config.py(python脚本)执行上传注册,可以参考https://blog.csdn.net/ZHANGLIZENG/article/details博客

transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableClientBatchSendRequest=true
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
# server
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
server.distributedLockExpireTime=10000
# store
#model改为db
store.mode=db
store.lock.mode=file
store.session.mode=file
# 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.cj.jdbc.Driver
# 改为上面创建的seata服务数据库
store.db.url=jdbc:mysql://ip:port/umapp_appcenter?useUnicode=true&rewriteBatchedStatements=true
# 改为自己的数据库用户名
store.db.user=appcenter
# 改为自己的数据库密码
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
store.redis.mode=single
store.redis.single.host=127.0.0.1
store.redis.single.port=6379
# store.redis.sentinel.masterName=""
# store.redis.sentinel.sentinelHosts=""
store.redis.maxConn=10
store.redis.minConn=1
store.redis.maxTotal=100
store.redis.database=0
# store.redis.password=""
store.redis.queryLimit=100
# log
log.exceptionRate=100
# metrics
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898
# service
# 自己命名一个vgroupMapping
service.vgroupMapping.my_test_tx_group=default
service.default.grouplist=ip:port
service.enableDegrade=false
service.disableGlobalTransaction=false
# 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=false
client.rm.tableMetaCheckerInterval=60000
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
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
client.undo.logTable=undo_log
client.undo.compress.enable=true
client.undo.compress.type=zip
client.undo.compress.threshold=64k

注意点

①.service.vgroupMapping.my_test_tx_group=default
中的my_test_tx_group需要与bootstrap.yml中配置的seata.tx-service-group的值一致。

②.service.vgroupMapping.my_test_tx_group=default
配置的default必须要等于registry.conf中配置的cluster="default"。

③.store.mode=db配置为db的方式,则需要配置db数据库方式的连接信息
store.db.url、store.db.user、store.db.password,此数据库存储下存放的表
global_table、branch_table、lock_table,用于记录全局性的事务信息

④.store.db.driverClassName的配置
mysql5.+使用 driverClassName = "com.mysql.jdbc.Driver"
mysql8使用 driverClassName = "com.mysql.cj.jdbc.Driver"

⑤.service.default.grouplist=ip:port为访问seata服务器的地址和端口(仅注册中心为file时使用),8091是默认端口,
也可以修改启动端口,在启动项目时加上端口:
seata-server.bat -p 18091
sh seata-server.sh -p 18091

⑥seata server需要配置集群时,只需要在启动seata server服务时指定不同的端口和节点序号即可,配置file.conf和registry.conf的内容一致,

windows下启动:

seata-server.bat -p 18091 -n 1

seata-server.bat -p 8091 -n 2

linux下启动:
sh seata-server.sh -p 18091 -n 1

sh seata-server.sh -p 8091 -n 2

⑦客户端启动时,可以看是否成功注册到seata server服务器

3.创建需要的事务表

global_table:全局事务表
branch_table:分支信息表
lock_table:加锁的表
以上三个表需要创建在seata服务器操作的db上,即file.conf中配置的数据库。

--全局事务表--
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;
 
-- 分支表
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;
 
-- 锁定表
CREATE TABLE IF NOT EXISTS `lock_table`
(
    `row_key`        VARCHAR(128) NOT NULL,
    `xid`            VARCHAR(128),
    `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新版本加的锁表
CREATE TABLE IF NOT EXISTS `distributed_lock`
(
    `lock_key`       CHAR(20) NOT NULL,
    `lock_value`     VARCHAR(20) NOT NULL,
    `expire`         BIGINT,
    PRIMARY KEY (`lock_key`)
    ) ENGINE = INNODB
    DEFAULT CHARSET = utf8mb4;
 
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);

undo_log:回滚日志表
在每个需要开启seata事务操作的数据库下都需要建立此表。

--日志文件表--
CREATE TABLE IF NOT EXISTS `undo_log`
(
    `branch_id`     BIGINT       NOT NULL COMMENT 'branch transaction id',
    `xid`           VARCHAR(128) 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
    AUTO_INCREMENT = 1
    DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table';

注意点:

seata1.4.2之后,需要回滚的表日期类型不能使用datetime,可以使用timestamp

4.客户端配置

需要开启seata事务的客户端,需要配置seata的注册和配置中心,使用相关注解进行事务开启。

(1)bootstrap.yml

向项目中添加配置信息,配置项的值与seata服务器的registry.conf中一致。

seata:
  enabled: true
  enable-auto-data-source-proxy: true #是否开启数据源自动代理,默认为true
  tx-service-group: my_test_tx_group  #要与配置文件中的vgroupMapping一致
  registry:  #registry根据seata服务端的registry配置
    type: nacos #默认为file
    nacos:
      application: seata-server #配置自己的seata服务
      server-addr: #根据自己的seata服务配置
      username: nacos #根据自己的seata服务配置
      password: nacos #根据自己的seata服务配置
      namespace:  #根据自己的seata服务配置
      cluster: default # 配置自己的seata服务cluster, 默认为 default
      group: SEATA_GROUP #根据自己的seata服务配置
  config:
    type: nacos #默认file,如果使用file不配置下面的nacos,直接配置seata.service
    nacos:
      server-addr: #配置自己的nacos地址
      group: SEATA_GROUP #配置自己的dev
      username: nacos #配置自己的username
      password: nacos #配置自己的password
      namespace:  #配置自己的namespace
      dataId: seataServer.properties #配置自己的dataId,由于搭建服务端时把客户端的配置也写在了seataServer.properties,所以这里用了和服务端一样的配置文件,实际客户端和服务端的配置文件分离出来更好

(2)spring boot 启动程序添加数据自动代理

使用注解:@EnableAutoDataSourceProxy

例子:

@EnableAutoDataSourceProxy
@EnableDiscoveryClient
@SpringBootApplication
public class UmappCloudServiceAppcenterApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(UmappCloudServiceAppcenterApplication.class, args);
    }
 
}

(3)使用注解开启事务

@ApiOperation("添加测试数据")
@PostMapping("/addUmappTestSeata")
@GlobalTransactional
@GlobalLock
public Result<UmappTest> addUmappTestSeata(String name,Integer age,String sex) {
    Result<UmappTest> result = umappTestService.addUmappTest(name,age,sex);
    Result temp = seataTestFeign.addSeataTest();//添加seata测试数据
    //int i = 1/0;
    return result;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章