seata

nacos & seata AT模式 & 多数据源

下载seata 软件包
安装前提:安装了JDK

下载地址:https://github.com/seata/seata/releases
我这里下载的是最新版seata-server-1.4.1.tar.gz
初始化 Seata TC Server 的 db 数据库
DROP DATABASE IF EXISTS seata;
CREATE DATABASE seata DEFAULT CHARACTER SET utf8;

DROP TABLE IF EXISTS seata.global_table;
CREATE TABLE seata.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;

DROP TABLE IF EXISTS seata.branch_table;
CREATE TABLE seata.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;

DROP TABLE IF EXISTS seata.lock_table;
CREATE TABLE seata.lock_table
(
    `row_key`        VARCHAR(128) NOT NULL,
    `xid`            VARCHAR(96),
    `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;
修改 conf/file 配置文件

修改使用 db 数据库,实现 Seata TC Server 的全局事务会话信息的共享

service {
  vgroupMapping.multi-datasource-service-group = "default"
}
## 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 = "dbcp"
    ## mysql/oracle/postgresql/h2/oceanbase etc.
    dbType = "mysql"
    driverClassName = "com.mysql.cj.jdbc.Driver"
    url = "jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false"
    user = "root"
    password = "123456"
    minConn = 5
    maxConn = 100
    globalTable = "global_table"
    branchTable = "branch_table"
    lockTable = "lock_table"
    queryLimit = 100
    maxWait = 5000
  }
}
修改 conf/registry.conf 配置文件

设置使用 Nacos 注册中心

registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "nacos"
  loadBalance = "RandomLoadBalance"
  loadBalanceVirtualNodes = 10

  nacos {
    application = "seata-server"
    serverAddr = "192.168.199.112:8848"
    group = "seata_demo"
    namespace = "d197f572-96bf-400f-b21e-0f38a2198ef1"
    cluster = "default"
    username = "nacos"
    password = "nacos"
  }
  file {
    name = "file.conf"
  }
}

config {
  # file、nacos 、apollo、zk、consul、etcd3
  type = "nacos"

  nacos {
    serverAddr = "192.168.199.112:8848"
    namespace = "d197f572-96bf-400f-b21e-0f38a2198ef1"
    group = "seata_demo"
    username = "nacos"
    password = "nacos"
  }
  
  file {
    name = "file.conf"
  }
}

导入配置信息到 Nacos 配置中心

Seata 官方提供了将配置信息(file.conf)批量导入到各种主流配置中心的 Shell 脚本,存放路径是在 Seata源码目录 script/config-center 目录

其中 config.txt 为通用参数文件,包含了 Seata Server(TC)需要的所有配置信息,需要根据实际情况更改文件里的以下内容

service.vgroupMapping.multi-datasource-service-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/seata?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false
store.db.user=root
store.db.password=123456
sh nacos-config.sh -h 127.0.0.1 -p 8848 -t d197f572-96bf-400f-b21e-0f38a2198ef1 -g seata_demo

在这里插入图片描述

启动 TC Server
启动第一个 TC Server 在后台
nohup sh bin/seata-server.sh -p 18091 -n 1 &

启动第二个 TC Server 在后台
nohup sh bin/seata-server.sh -p 28091 -n 2 &

在这里插入图片描述

运行项目

代码地址

初始化数据库

使用代码地址中,data.sql 脚本,创建 seata_order、seata_storage、seata_amount 三个库

然后启动项目,确保启动过程中没有任何报错信息,我遇到了如下错误,应该都是之前配置没对,得仔细检查

can not get cluster name in registry config 'service.vgroupMapping.multi-datasource-service-group', please make sure registry config correct

no available service 'null' found, please make sure registry config correct

在这里插入图片描述

简单测试
分布式事务正常提交

目前数据库的数据情况

mysql> select * from seata_order.orders;
Empty set (0.00 sec)

mysql> select * from seata_product.product;
+----+-------+---------------------+
| id | stock | last_update_time    |
+----+-------+---------------------+
|  1 |    10 | 2021-03-25 18:28:49 |
+----+-------+---------------------+
1 row in set (0.00 sec)

mysql> select * from seata_account.account;
+----+---------+---------------------+
| id | balance | last_update_time    |
+----+---------+---------------------+
|  1 |      10 | 2021-03-25 18:28:49 |
+----+---------+---------------------+
1 row in set (0.00 sec)

创建订单接口

扫描二维码关注公众号,回复: 13132110 查看本文章
@Override
@DS(value = "order-ds")
@GlobalTransactional
public Integer createOrder(Long userId, Long productId, Integer price) throws Exception {
    Integer amount = 1; // 购买数量,暂时设置为 1。

    logger.info("[createOrder] 当前 XID: {}", RootContext.getXID());

    // 扣减库存
    productService.reduceStock(productId, amount);

    // 扣减余额
    accountService.reduceBalance(userId, price);

    // 保存订单
    OrderDO order = new OrderDO().setUserId(userId).setProductId(productId).setPayAmount(amount * price);
    orderDao.saveOrder(order);
    logger.info("[createOrder] 保存订单: {}", order.getId());

    // 返回订单编号
    return order.getId();
}

使用 Postman 模拟调用 http://127.0.0.1:8081/order/create 创建订单的接口
在这里插入图片描述

此时控制台日志,显示如下
在这里插入图片描述

再查询下目前数据库的数据情况
在这里插入图片描述

分布式事务异常回滚

使用 Postman 模拟调用 http://127.0.0.1:8081/order/create 创建订单的接口
在这里插入图片描述

控制台日志
在这里插入图片描述

再查询下目前数据库的数据情况
在这里插入图片描述

参考:

分布式事务,这一篇就够了

分布式事务 Seata 及其三种模式详解 | Meetup#3 回顾

Seata 入门教程 - 实战篇(电商)

Seata 极简入门

芋道 Spring Boot 分布式事务 Seata 入门

猜你喜欢

转载自blog.csdn.net/yfm081616/article/details/115221705