安装Seata

下载Seata Server安装包

Seata 安装包的下载网址为网址7,本书选择的版本是 1.4.2,下载网址为网址8。

选择 Seata 1.4.2 版本的原因主要是参考了官方组件版本的对应关系,本书中所使用的 Spring Cloud Alibaba 的版本为 2021.0.1.0,官方推荐 Spring Cloud Alibaba 2021.0.1.0 对应的 Nacos 版本为 1.4.2。

下载成功后,会得到一个名称为 seata-server-1.4.2.zip 的文件,解压缩后的目录结构如下。

  • bin:存放启动 Seata Server 的脚本文件。

  • conf:Seata Server 的配置目录。

  • lib:Seata Server 的 Jar 包存放目录。

  • logs:存放日志文件。

下载并解压缩后,还需要对关键配置做一些更改。

Seata Server 的持久化配置

Seata Server 作为全局事务的管理者,需要记录和存储一些数据,因此需要存储介质来做数据持久化的工作。

Seata 支持 file、db、redis 三种持久化模式。file 是本地文件;db 是数据库,如 MySQL、Oracle、OceanBase 等;redis 就是使用 Redis 作为存储介质。默认情况下,Seata 使用本地文件来做持久化工作,本地文件的方式不适合后期 Seata Server 的集群拓展,因此建议把 Seata Server 持久化方案修改为 db 或 redis 的方式。本书使用 MySQL 来做 Seata Server 的持久化工作。接下来是具体的操作流程。

在 Seata 安装目录下的 conf 文件夹中,有一个名称为 file.conf 的文件,这个文件就是用来配置 Seata Server 持久化方式的。打开这个文件,并做如下修改。

  1. 修改存储方式。

    将 mode 配置项修改为 db,代码如下:

    store {
      ## store mode: file、db、redis
      mode = "db"
    }
  2. 配置 MySQL 的连接信息。

    相关的配置项同样是在 file.conf 文件中,只需要把数据库地址、登录用户和登录密码修改成自己的,其他配置项使用默认设置即可。最终配置内容如下:

    # transaction log store, only used in seata-server
    store {
      # store mode: file, db, redis
      mode = "db"
    
      # database store property
      db {
        # the implement of javax.sql.DataSource, such as DruidDataSource (druid)/
        # BasicDataSource (dbcp) / HikariDataSource (hikari) etc.
        datasource = "Druid"
        # mysql/oracle/postgresql/h2/oceanbase etc.
        dbType = "mysql"
        driverClassName = "com.mysql.cj.jdbc.Driver"
        # if using mysql to store the data, recommend add
        rewriteBatchedStatements=true in jdbc connection param
    
        # 修改为自己的数据库地址链接,数据库名称为 seata_server_db (可自行定义)
        url = "jdbc:mysql://127.0.0.1:3306/seata_server_db?rewriteBatchedStatements=
    true&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false"
        # 修改为自己的数据库登录用户
        user = "root"
        # 修改为自己的数据库登录密码
        password = "123456"
        minConn = 5
        maxConn = 100
        globalTable = "global_table"
        branchTable = "branch_table"
        lockTable = "lock_table"
        queryLimit = 100
        maxWait = 5000
      }
    }
  3. 新建数据库并创建表结构。

打开数据库操作工具,新建 seata_server_db 数据库,之后导入 Seata Server 所需的表结构。具体的建表语句 Seata 官方已经提供了,见网址9。

最终的建库、建表 SQL 内容如下:

# 新建 seata_server 数据库
CREATE DATABASE /*!32312 IF NOT EXISTS*/`seata_server_db` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `seata_server_db`;

# 以下语句是官方提供的
-- 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 NOT NULL,
  `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);

当然,这些字段的定义中某些参数是可以根据自身系统进行修改的。比如,lock_table 表中的 table_name 字段,部分业务表的表名太长导致超出了 32 个字符长度,在执行分布式事务流程时就会报错。那么,在建表时就可以把这个字段的长度增加,如 VARCHAR(64) 或 VARCHAR(128),这一点需要格外注意。

直接导入 seata_server_db 数据库即可,导入成功后的数据库结构如图 10-18 所示。

image 2025 04 18 10 33 35 751
Figure 1. 图10-18 seata_server_db 数据库结构

另外,读者需要注意的一点是,这个数据库与微服务中的数据库并没有什么关系,只需要把数据库当作 Seata Server 中间件的一部分即可。