up:: SpringCloud分布式事务原理

说明:

本节开始对项目添加分布式事务。。。

代码沿用SpringCloud之Gateway新网关开发

跟着文档进行操作 seata-samples/quick-integration-with-spring-cloud.md at master · seata/seata-samples · GitHub

添加依赖

<dependencies>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>2.1.4.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
</dependencies>

然后涉及分布式事务的订单模块和商品模块添加下列依赖:

<dependency>
	<groupId>com.alibaba.cloud</groupId>
	<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

添加配置

注意:涉及事务操作的模块都要添加下列配置,在商品模块和订单模块进行配置:

seata.tx-service-group=imooc_cloud_mall
seata.service.vgroup-mapping.imooc_cloud_mall=default
seata.service.grouplist.default = 127.0.0.1:8091

事务分组:seata的资源逻辑,可以按微服务的需要,在应用程序(客户端)对自行定义事务分组,每组取一个名字。 集群:seata-server服务端一个或多个节点组成的集群cluster。 应用程序(客户端)使用时需要指定事务逻辑分组与Seata服务端集群的映射关系,Seata中配置相同的cluster名称就表示组成一个集群组。

事务分组如何找到Seata集群:

首先应用程序(客户端)中通过seata.tx-service-group配置了事务分组。 应用程序(客户端)会通过用户配置的配置中心去寻找service.vgroupMapping .[事务分组配置项],取得配置项的值就是TC集群的名称。若应用程序是SpringBoot则通过seata.service.vgroup-mapping.事务分组名=集群名称 配置 拿到集群名称程序通过一定的前后缀+集群名称去构造服务名,各配置中心的服务名实现不同(前提是Seata-Server已经完成服务注册,且Seata-Server向注册中心报告cluster名与应用程序(客户端)配置的集群名称一致) 拿到服务名去相应的注册中心去拉取相应服务名的服务列表,获得后端真实的TC服务列表(即Seata-Server集群节点列表)

seata:
  # 事务组的名称,对应service.vgroupMapping.default_tx_group=xxx中配置的default_tx_group
  tx-service-group: default_tx_group
  # 配置事务组与集群的对应关系
  service:
    vgroup-mapping:
      # default_tx_group为事务组的名称,default为集群名称
      default_tx_group: default

打开Seata-Server:

配置回滚数据库

数据源面试三连杀:是啥?为什么要用?怎么用? - 知乎

我们的事务操作需要多表多数据源结构

我们的order模块和product模块共用一张数据库,我们需要分开。。。

分布式事务:采用多数据源之后,事务的实现方式也随之发生变化。当某个数据源操作出现异常时,该数据源和其他数据源的事务都需要回滚。这种涉及多个数据源的事务,称为分布式事务

说明: order订单模块对应imooc_mall数据库,product模块对应imooc_mall_prepare数据库。。。

每个数据库都要引入undo_log表。


Undo Log 如何保障事务的原子性呢?

具体的方式为:在操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方称为 Undo Log),然后进行数据的修改。如果出现了错误或者用户执行了 Rollback 语句,系统可以利用 Undo Log 中的备份将数据恢复到事务开始之前的状态。

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

添加注解

测试分布式事务是否成功?

这里代码实操沿用SpringCloud之Gateway新网关开发,启动方式也是和前面进阶开发的 一样。。。

用户登陆后,添加商品到购物车,然后生成订单,注意需要jwt认证:


两个数据库情况:

商品模块:

订单模块;

继续运行,是否回滚?