SprinrBoot整合Seata使用AT模式解决多数据源分布式事务

SprinrBoot整合Seata使用AT模式解决多数据源分布式事务

分布式事务场景:

1.应用中使用多数据源,跨多个数据库

2.跨多个应用进程

Seata是阿里巴巴开源的分布式事务中间件,以高效并且对业务0 侵入的方式,解决微服务场景下面临的分布式事务问题。

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

进入官网不会下载,请参考如下截图:


1.下载Window版本后,打开如图所示

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.然后进入seata-server1.4.2\conf目录中修改对应的参数
image.png
4.开始编辑file.conf文件
5.配置seata-server-1.4.2/conf/registry.conf
6.下载Seata对应的Mysql脚本:https://github.com/seata/seata/blob/develop/script/server/db/mysql.sql
下面还有Oracle数据库的脚本,也可以前往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对应的脚本如下:
创建名称为seata的数据库,字符集utf8mb4、排序规则utf8mb4_general_ci
nacos的配置首先要修改连接的数据库,在oracle新建一个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
# 这里是个坑OracleDriver并不存在在seata服务代码里
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.业务数据库中添加项目数据库undo_log(就是你应用平台的数据库)
和mysql一样,项目数据库也需要每个库都加入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.创建nacos-config.sh
内容从Github链接nacos-config.sh中复制粘贴即可
10.然后再来看一下Seata的官方文档
打开找到Nacos配置中心(Nacos是目前最主流的注册中心)
执行命令自动构建Nacos配置
11.启动Nacos创建一个命令空间如图
12.初始化脚本数据到nacos
在执行以下命令,将配置自动加载到Nacos中
sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 此为上面的Nacos的Namespace的ID -u nacos -w nacos
然后查看Nacos中是否有配置
13.下载的Nacos中脚本下载说明

14.直接访问在Github中获取Seata中所需的文件

点击 参考部署指南
到Github获取sql脚本/各个配置中心参数导入脚本,config.txt/server端数据库脚本
15.SpringBoot中添加配置
也可以参考官方文档http://seata.io/zh-cn/docs/ops/deploy-guide-beginner.html
点击查看官方文档
      
        
            com.alibaba.cloud
            spring-cloud-alibaba-seata
            2.2.0.RELEASE
            
                
                    io.seata
                    seata-spring-boot-starter
                
            
        

        
            io.seata
            seata-spring-boot-starter
            1.4.0
            
                
                    druid
                    com.alibaba
                
            
        

yaml应用服务配置

seata: ## Seata分布式事务配置管理
  enabled: true
  enable-auto-data-source-proxy: true
  # seata 事务组编号 用于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:
    # 必须写nacos,否则默认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:
    # 事务组对应的集群名称
    vgroup-mapping:
      default_tx_group: default
    disable-global-transaction: false
  client:
    rm:
      report-success-enable: false


15.如果以上都配置完毕,就启动Seata/应用服务
BUG问题
can not get cluster name in registry config 
'service.vgroupMapping.account-service-fescar-service-group'
please make sure registry config correct
说明没有配置正确,如下,必须保证 type 为 nacos,namespace、group
也必须和 seata-server 注册时的数据统一才可以
16.代码应用

17.官网示例参考
http://seata.io/zh-cn/docs/user/quickstart.html

你可能感兴趣的:(SprinrBoot整合Seata使用AT模式解决多数据源分布式事务)