分佈式事務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;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章