SprinrBoot整合Seata使用AT模式解決多數(shù)據(jù)源分布式事務(wù)

SprinrBoot整合Seata使用AT模式解決多數(shù)據(jù)源分布式事務(wù)

分布式事務(wù)場(chǎng)景:

1.應(yīng)用中使用多數(shù)據(jù)源,跨多個(gè)數(shù)據(jù)庫(kù)

2.跨多個(gè)應(yīng)用進(jìn)程

Seata是阿里巴巴開(kāi)源的分布式事務(wù)中間件,以高效并且對(duì)業(yè)務(wù)0 侵入的方式,解決微服務(wù)場(chǎng)景下面臨的分布式事務(wù)問(wèn)題。

Seata下載地址:https://github.com/seata/seata/releases

進(jìn)入官網(wǎng)不會(huì)下載,請(qǐng)參考如下截圖:


1.下載Window版本后,打開(kāi)如圖所示

2.其中Context.txt配置如圖


service.vgroupMapping.default_tx_group=default
store.mode=db
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1/:3306/nacos-mysql?useUnicode=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

3.然后進(jìn)入seata-server1.4.2\conf目錄中修改對(duì)應(yīng)的參數(shù)
image.png
4.開(kāi)始編輯file.conf文件
5.配置seata-server-1.4.2/conf/registry.conf
6.下載Seata對(duì)應(yīng)的Mysql腳本:https://github.com/seata/seata/blob/develop/script/server/db/mysql.sql
下面還有Oracle數(shù)據(jù)庫(kù)的腳本,也可以前往Github獲得所有SQl腳本
-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- the table to store GlobalSession data
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_status_gmt_modified` (`status` , `gmt_modified`),
    KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4;

-- the table to store BranchSession data
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 = utf8mb4;

-- the table to store lock data
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),
    `status`         TINYINT      NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',
    `gmt_create`     DATETIME,
    `gmt_modified`   DATETIME,
    PRIMARY KEY (`row_key`),
    KEY `idx_status` (`status`),
    KEY `idx_branch_id` (`branch_id`),
    KEY `idx_xid_and_branch_id` (`xid` , `branch_id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4;

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);
7.如果是Oracle對(duì)應(yīng)的腳本如下:
創(chuàng)建名稱為seata的數(shù)據(jù)庫(kù),字符集utf8mb4、排序規(guī)則utf8mb4_general_ci
nacos的配置首先要修改連接的數(shù)據(jù)庫(kù),在oracle新建一個(gè)SEATA命名空間和用戶,并插入三張表(global_table,branch_table,lock_table),腳本如下
-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- the table to store GlobalSession data
CREATE TABLE global_table
(
    xid                       VARCHAR2(128) NOT NULL,
    transaction_id            NUMBER(19),
    status                    NUMBER(3)     NOT NULL,
    application_id            VARCHAR2(32),
    transaction_service_group VARCHAR2(32),
    transaction_name          VARCHAR2(128),
    timeout                   NUMBER(10),
    begin_time                NUMBER(19),
    application_data          VARCHAR2(2000),
    gmt_create                TIMESTAMP(0),
    gmt_modified              TIMESTAMP(0),
    PRIMARY KEY (xid)
);

CREATE INDEX idx_gmt_modified_status ON global_table (gmt_modified, status);
CREATE INDEX idx_transaction_id ON global_table (transaction_id);

-- the table to store BranchSession data
CREATE TABLE branch_table
(
    branch_id         NUMBER(19)    NOT NULL,
    xid               VARCHAR2(128) NOT NULL,
    transaction_id    NUMBER(19),
    resource_group_id VARCHAR2(32),
    resource_id       VARCHAR2(256),
    branch_type       VARCHAR2(8),
    status            NUMBER(3),
    client_id         VARCHAR2(64),
    application_data  VARCHAR2(2000),
    gmt_create        TIMESTAMP(6),
    gmt_modified      TIMESTAMP(6),
    PRIMARY KEY (branch_id)
);

CREATE INDEX idx_xid ON branch_table (xid);

-- the table to store lock data
CREATE TABLE lock_table
(
    row_key        VARCHAR2(128) NOT NULL,
    xid            VARCHAR2(96),
    transaction_id NUMBER(19),
    branch_id      NUMBER(19)    NOT NULL,
    resource_id    VARCHAR2(256),
    table_name     VARCHAR2(32),
    pk             VARCHAR2(36),
    gmt_create     TIMESTAMP(0),
    gmt_modified   TIMESTAMP(0),
    PRIMARY KEY (row_key)
);

CREATE INDEX idx_branch_id ON lock_table (branch_id);
修改seata配置
store.db.dbType=oracle
# 這里是個(gè)坑OracleDriver并不存在在seata服務(wù)代碼里
store.db.driverClassName=oracle.jdbc.OracleDriver
store.db.url=jdbc:oracle:thin:@192.168.1.135:1521:helowin
store.db.user=SEATA
store.db.password=SEATA
8.業(yè)務(wù)數(shù)據(jù)庫(kù)中添加項(xiàng)目數(shù)據(jù)庫(kù)undo_log(就是你應(yīng)用平臺(tái)的數(shù)據(jù)庫(kù))
和mysql一樣,項(xiàng)目數(shù)據(jù)庫(kù)也需要每個(gè)庫(kù)都加入undo_log表,腳本如下
-- for AT mode you must to init this sql for you business database. the seata server not need it.
CREATE TABLE undo_log
(
    id            NUMBER(19)    NOT NULL,
    branch_id     NUMBER(19)    NOT NULL,
    xid           VARCHAR2(100) NOT NULL,
    context       VARCHAR2(128) NOT NULL,
    rollback_info BLOB          NOT NULL,
    log_status    NUMBER(10)    NOT NULL,
    log_created   TIMESTAMP(0)  NOT NULL,
    log_modified  TIMESTAMP(0)  NOT NULL,
    PRIMARY KEY (id),
    CONSTRAINT ux_undo_log UNIQUE (xid, branch_id)
);

COMMENT ON TABLE undo_log IS 'AT transaction mode undo table';

-- Generate ID using sequence and trigger
CREATE SEQUENCE UNDO_LOG_SEQ START WITH 1 INCREMENT BY 1;
9.創(chuàng)建nacos-config.sh
內(nèi)容從Github鏈接nacos-config.sh中復(fù)制粘貼即可
10.然后再來(lái)看一下Seata的官方文檔
打開(kāi)找到Nacos配置中心(Nacos是目前最主流的注冊(cè)中心)
執(zhí)行命令自動(dòng)構(gòu)建Nacos配置
11.啟動(dòng)Nacos創(chuàng)建一個(gè)命令空間如圖
12.初始化腳本數(shù)據(jù)到nacos
在執(zhí)行以下命令,將配置自動(dòng)加載到Nacos中
sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 此為上面的Nacos的Namespace的ID -u nacos -w nacos
然后查看Nacos中是否有配置
13.下載的Nacos中腳本下載說(shuō)明

14.直接訪問(wèn)在Github中獲取Seata中所需的文件

點(diǎn)擊 參考部署指南
到Github獲取sql腳本/各個(gè)配置中心參數(shù)導(dǎo)入腳本,config.txt/server端數(shù)據(jù)庫(kù)腳本
15.SpringBoot中添加配置
也可以參考官方文檔http://seata.io/zh-cn/docs/ops/deploy-guide-beginner.html
點(diǎn)擊查看官方文檔
      <!--seata 分布式事務(wù)(使用這種方式可以自動(dòng)傳遞xid)-->
        <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>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
            <version>1.4.0</version>
            <exclusions>
                <exclusion>
                    <artifactId>druid</artifactId>
                    <groupId>com.alibaba</groupId>
                </exclusion>
            </exclusions>
        </dependency>

yaml應(yīng)用服務(wù)配置

seata: ## Seata分布式事務(wù)配置管理
  enabled: true
  enable-auto-data-source-proxy: true
  # seata 事務(wù)組編號(hào) 用于TC集群名  # 必須和config.txt里面配置的屬性一致
  tx-service-group: default_tx_group
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      username: nacos
      password: nacos
  config:
    # 必須寫(xiě)nacos,否則默認(rèn)file
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      username: nacos
      password: nacos
      namespace: nacos的namespaced例如:65f556f2-1dc4-4b13-af44-6914f7f5bf73
  service:
    # 事務(wù)組對(duì)應(yīng)的集群名稱
    vgroup-mapping:
      default_tx_group: default
    disable-global-transaction: false
  client:
    rm:
      report-success-enable: false


15.如果以上都配置完畢,就啟動(dòng)Seata/應(yīng)用服務(wù)
BUG問(wèn)題
can not get cluster name in registry config 
'service.vgroupMapping.account-service-fescar-service-group'
please make sure registry config correct
說(shuō)明沒(méi)有配置正確,如下,必須保證 type 為 nacos,namespace、group
也必須和 seata-server 注冊(cè)時(shí)的數(shù)據(jù)統(tǒng)一才可以
16.代碼應(yīng)用

17.官網(wǎng)示例參考
http://seata.io/zh-cn/docs/user/quickstart.html
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容