接上文 SpringCloud Alibaba - Sentinel
1.简介(Seata与分布式事务)

Seata官方网址https://seata.io/zh-cn/docs/overview/what-is-seata.html

 
2.环境搭建
首先对之前的图书借阅系统进行升级:
 
 
 
编写对应的服务接口。
(1)用户服务

 
 
 
(2)图书服务

 
 
 
(3)借阅服务

 
 
 
 


 
测试存在的问题
用户1号借阅1号书,显示已被借阅
 
 
 1号借2号书则成功
 
 
 
3.分布式事务解决方案
1.常用的分布式事务解决方案
1. XA分布式事务协议-2PC

2PC-存在的问题
3.2 XA分布式事务协议-3PC

3PC-存在的问题

3.3 TCC(补偿事务)
 
4 Seata机制

4.1 Seata的四种事务模式

4.2 使用file模式部署

https://github.com/seata/seata/releases/download/v1.4.2/seata-server-1.4.2.zip
https://github.com/seata/seata/archive/refs/heads/develop.zip

 接着将各个服务作为Seata的客户端,只需导入依赖即可。其他服务同理
 
添加配置文件
 

 
 
 给每个服务启动类添加注解@EnableAutoDataSourceProxy。



配置完重启所有的服务,此时重启后所有服务都连接到seata,但是没有开启任何的分布式服务。 接着通过注解添加分布式服务,添加完重启borrow服务。

此时因为Seata会分析修改数据的sql,同时生成对应的反向回滚SQL,这个回滚记录会放在undo_log表中,因此要求每个client都要有一个对应的undo_log表,(即每个服务连接的数据库都需要创建这样一个表,这里因为三个服务都用的一个数据库,因此只在这个数据库中添加一个undo_log即可)。sql定义如下:
CREATE TABLE `undo_log`
(
  `id`            BIGINT(20)   NOT NULL AUTO_INCREMENT,
  `branch_id`     BIGINT(20)   NOT NULL,
  `xid`           VARCHAR(100) NOT NULL,
  `context`       VARCHAR(128) NOT NULL,
  `rollback_info` LONGBLOB     NOT NULL,
  `log_status`    INT(11)      NOT NULL,
  `log_created`   DATETIME     NOT NULL,
  `log_modified`  DATETIME     NOT NULL,
  `ext`           VARCHAR(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8;
 
创建完表重启三个服务,此时已配置完成。
 然后重置以下表的数据,分别如下:
 book表
 
 借阅表
 
 用户表
 
seata
 
然后进行访问借阅接口进行效果测试。
测试1:1号人第一次借1号书。结果:成功
 
 测试2:1号人再次借1号书。结果:失败
 
 
 此时seata会将该方法中的事务回滚,可以看到书籍数量没有减少
 
 测试3:1号人借2号书一次。结果:成功
 
 书籍数量减少
 
 再次借阅则失败
 
 书籍数量未减少
 
 此时在同一事务内的XID是一样的。
4.3 使用Nacos模式部署
先单独为Seata配置一个命名空间
先关闭nacos和所有服务。然后修改seata目录conf下的配置文件register.conf。

到此注册信息配置完。
注册信息配置完之后,需要将配置文件放到Nacos中,让Nacos管理配置,就可以进行热更新,直接在nacos中修改。
 
 配置完然后回车
 
然后可以在nacos看到对应的配置:
然后需要将对应的事务组应映射配置也添加上,Datald格式为service.vgroupMapping.事务组名称,比如我们使用默认的名称,值全部default即可。在nacos配置事务组。

 

 然后将对应的事务组映射配置也添加上,DataId格式为 service.vgroupMapping.事务组名称。此处使用默认的名称,值全部default即可。


 
接着将book-service和borrow-service同样的形式在nacos上配置事务组,即上边紧挨的两张图。

 
 
到此完成了服务端的Nacos配置,接着需要对客户端也进行Nacos配置;

 将本地改为nacos服务端。
 
其他user-service和book-service同理。配置完启动seata和三个服务。
 
 
 然后重置数据库进行nacos上的seata测试。
 
 

 测试1:1号人借1号书。 结果:成功
 
 书籍数量减少
 
 生成借阅信息
 
 再次测试 ,可以看到效果和file类型是一样的,1号人借1号书,结果:借阅失败,书籍数量未减少,不过现在的注册和配置都继承在nacos中了。
 
 
还可配置会话信息的存储方式,默认是file类型,那么就会在运行目录下 创建file_store目录,可以将其搬到数据库中存储,只需修改配置即可。
先将所有服务关闭。
 
 
 同理进入编辑
 
 改为db进行保存
 
 
 然后修改数据库驱动、URL、用户名密码
 
 修改url
 

 修改用户名密码
 
 操作数据库
 创建用户并给权限

 创建数据库表
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`)
) 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 ('HandleAllSession', ' ', 0);
 

 然后重启seata,看到数据源绑定成功:
 
 重启所有服务,重置数据库和之前的类似。
 
 进行借阅信息,但是报错显示服务名称过长。
 

 解决过长问题,修改数据库字段类型,然后保存。
 
 再次进行借阅两次,第一次显示成功,第二次显示已被借阅,书籍数量未减少。
 
 
 

 到此关于nacos模式下的Seata部署就完成了。
 但此时若在高并发请求下,同一时间100个人借同一个书,但同一个书只有3本,可能不会正常的只借出3本书。





























