后端微服务基础架构Spring Cloud

版本关系

版本发布说明-阿里云Spring Cloud Alibaba官网

选择

创建项目

创建父项目

什么都不动,创建即可

1) 删掉没用的文件

保留

2) pom中加入

复制代码
打包方式  <packaging>pom</packaging>

3) 删掉src

4) pom.xml中删除没用的

5)更改pom.xml中

复制代码
spring-boot-starter-parent版本为更改为3.3.4,点击右上角的maven标记刷新依赖

删掉依赖

properties更换为

复制代码
  <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-cloud.version>2023.0.3</spring-cloud.version>
        <spring-cloud-alibaba.version>2023.0.3.2</spring-cloud-alibaba.version>
    </properties>

再加入:刷新

复制代码
<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

完整的:

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <packaging>pom</packaging>
    <groupId>com.i7i8i9</groupId>
    <artifactId>weifuwu3</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>weifuwu3</name>
    <description>weifuwu3</description>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-cloud.version>2023.0.3</spring-cloud.version>
        <spring-cloud-alibaba.version>2023.0.3.2</spring-cloud-alibaba.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

创建最外层服务

1.创建module ---services

就是个普通java module,不用选add sample code

pom中也是加入打包方式

<packaging>pom</packaging>

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>weifuwu3</artifactId>
        <groupId>com.i7i8i9</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>services</artifactId>
    <packaging>pom</packaging>
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

删除src

创建微服务

新建module ,主要是确认一定在上面建立的services服务下,不用选add sample code,Parent一定要对,

创建完成后,在父级服务pom中可以看到<modules>

查看maven结构

可以点击齿轮,选中Group Modules

完善项目

导入公共依赖

主要是在最外层services pom.xml中加入,比如nacos

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>weifuwu3</artifactId>
        <groupId>com.i7i8i9</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>services</artifactId>
    <packaging>pom</packaging>
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
<!--        导入nacos-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>
</project>

在各层服务依赖中查看

启动

给每个微服务pom.xml导入Web依赖

在某个微服务上点击右键 generate,选择 edit starters

不行自己导

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>weifuwu3</artifactId>
        <groupId>com.i7i8i9</groupId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../../pom.xml</relativePath>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>service-order</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

新建主程序

src/main/java下新建

com.i7i8i9.auth.AuthMainApplication

复制代码
package com.i7i8i9.order;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class OrderMainApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderMainApplication.class, args);
    }
}

编写application.yml

复制代码
spring.application.name=service-order
server.port=8080
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

Nacos

下载,启动

http://192.168.32.1:8848/nacos/index.html

基本原则

1.Gateway: 前后端之间会经过GateWay, 后端服务之间因为属于同一个工程,一般不经过

GateWay,但也可以经过

服务

1.目录

服务可以都放在服务模块下,但是需要在服务模块的pom.xml体现

pom.xml

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud-demo</artifactId>
        <groupId>com.i7i8i9</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <packaging>pom</packaging>
    <modelVersion>4.0.0</modelVersion>
    <modules>
        <module>service-product</module>
        <module>service-order</module>
        <module>seata-account</module>
        <module>seata-business</module>
        <module>seata-order</module>
        <module>seata-storage</module>
    </modules>

    <artifactId>services</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
   <dependencies>
<!--   sentinel是流量保护    -->
       <dependency>
           <groupId>com.alibaba.cloud</groupId>
           <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
       </dependency>
       <dependency>
             <!--        nucos 注册中心   服务发现-->
           <groupId>com.alibaba.cloud</groupId>
           <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
       </dependency>
       <!--      所有下属微服务的配置来源-->
       <dependency>
           <groupId>com.alibaba.cloud</groupId>
           <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
       </dependency>
       <dependency>
           <!-- openfeign 远程调用-->
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-openfeign</artifactId>
       </dependency>
       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <scope>annotationProcessor</scope>
       </dependency>
       <dependency>
           <groupId>com.i7i8i9</groupId>
           <artifactId>model</artifactId>
           <version>0.0.1-SNAPSHOT</version>
       </dependency>


   </dependencies>
</project>

Feign远程调用

指的是需要调用其他服务的服务

1.服务src下建立feign文件夹

2.服务主程序上加注释

复制代码
@EnableFeignClients(basePackages = "com.atguigu.business.feign")

3.Feign文件夹内建需要调用的抽象类客户端

主要目的是供serviceImp使用

快速的方式是去被调用controller方面里面复制

方法名前面可以去掉public

复制代码
package com.atguigu.business.feign;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;


@FeignClient(value="seata-storage")     //服务名称nacos里面有
public interface StorageFeignClient {

    //找到扣库存服务的接口复制其方法名和参数

    /**
     *
     * @param commodityCode
     * @param count
     * @return
     */
    @GetMapping("/deduct")
     String deduct(@RequestParam("commodityCode") String commodityCode,
                         @RequestParam("count") Integer count);
}

4.服务实现类

主要是装配Feign客户端,再调用其方法

复制代码
package com.atguigu.business.service.impl;

import com.atguigu.business.feign.OrderFeignClient;
import com.atguigu.business.feign.StorageFeignClient;
import com.atguigu.business.service.BusinessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
public class BusinessServiceImpl implements BusinessService {

    //第一步就是拿到远程服务客户端
    @Autowired
    StorageFeignClient storageFeignClient;

    @Autowired
    OrderFeignClient orderFeignClient;

    @Override
    public void purchase(String userId, String commodityCode, int orderCount) {
        //TODO 1. 扣减库存
        storageFeignClient.deduct(commodityCode,orderCount);
        //TODO 2. 创建订单
        orderFeignClient.create(userId,commodityCode,orderCount);
    }
}

GateWay

SpringCloud基础2------Nacos配置、Feign、Gateway-阿里云开发者社区

nacos(七): gateway(单体)-CSDN博客

创建服务

pom.xml引入gateway和loadbalence

复制代码
 <!--网关-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
        <!--消费者-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
            <version>3.1.5</version>
        </dependency>

新建module

加上服务发现@EnableDiscoveryClient

复制代码
package com.i7i8i9.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

启动

yml

application.yml

复制代码
spring:
  active: dev
  application:
     name: gateway
  cloud:
    nacos:
       discovery:
           server-addr: 127.0.0.1:8848
           username: nacos
           password: nacos
       config:
         server-addr: 127.0.0.1:8848
         file-extension: properties
         username: nacos
         password: nacos
       loadbalancer:
         nacos:
           enabled: true
    gateway:
       discovery:
         locator:
           enabled: true
       routes: # 网关路由配置
     #第一组网关路由配置,针对于服务service-auth
         - id: serviceAuth # 路由id,自定义,只要唯一即可
           uri: lb://service-auth # 指的是从nacos中按照名称获取微服务,并遵循负载均衡策略
           predicates: # 路由断言。也就是判断请求是否符合路由规则的条件。predicates译为谓语、断言
              - Path=/auth/** # 路径断言。当请求路径满⾜Path指定的规则时,才进⾏路由换发
           filters:
              - StripPrefix=1    # 拼接好url之后去掉1层路径也就是p1
    #http://localhost:10010/auth/token,因为/auth/路径触发了第一个路由规则,路由去掉p1这一项,重新拼接为lb://service-auth/auth去获取访问的结果。:
  datasource:
    driver-class-name: ${i7i8i9.datasource.driver-class-name}
    url: jdbc:mysql://${i7i8i9.datasource.host}:${i7i8i9.datasource.port}/${i7i8i9.datasource.database}?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
    username: ${i7i8i9.datasource.username}
    password: ${i7i8i9.datasource.password}
  • id: serviceAuth # 路由id,自定义,只要唯一即可

uri: lb://service-auth # 指的是从nacos中按照名称获取微服务,并遵循负载均衡策略

predicates: # 路由断言。也就是判断请求是否符合路由规则的条件。predicates译为谓语、断言

  • Path=/auth/** # 路径断言。当请求路径满⾜Path指定的规则时,才进⾏路由换发

filters:

  • StripPrefix=1 # 拼接好url之后去掉1层路径也就是p1

#http://localhost:10010/auth/token,因为/auth/路径触发了第一个路由规则,路由去掉p1这一项,重新拼接为lb://service-auth/auth去获取访问的结果。:

假设有个服务实际调用地址为

http://localhost:8085/token

则也可以用以下两种方式访问:

http://localhost:10010/service-auth/token 这种service-auth就是实际上nacos服务名称

http://localhost:10010/auth/token 这是标准的,auth就是上面的断言,就是当出现auth时就去调用nacos 里面的service-auth

404: 注意如果请求404则可能是最后面多了/

AxiosError {message: 'Network Error', name: 'AxiosError', code: 'ERR_NETWORK', config: {...}, request: XMLHttpRequest, ...}

application-dev.yml

复制代码
server:
  port: 10010 #当前spring boot工程运行时所占用的端口号

i7i8i9:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    host: 120.79.150.231 #主机地址
    port: 3306 #端口号
    database: basic #当前需要连接的数据库
    username: admin #用户
    password: tyuueew333444IIIIOOO88qqq #密码

服务查看

跨域

可以使用nginx

nginx: download

默认80端口

D:\soft\nginx-1.27.5\conf

复制代码
4

nginx -s reload

npm run build

事务

每个微服务都有对应的数据库

本地事务

主要是单接口测试,自己操作自己的数据库

操作数据库的服务的main主类上

@EnableTransactionManagement

一般ServiceImpl类会加

@Transactional

注意没有引入mybatis是没有这个注解的

全局事务-alibaba seata

本地事务要先配好

1.启动客户端Seata-绿色软件

下载Seata Java Download | Apache Seata

要使用2.1.0

两次解压,找到文件夹seata-server

点击bat文件即可启动

登录 http://localhost:7091/,账号密码都是seata 7091是网页端口

注意服务监听端口不是7091,而是8091

2.为服务总配置引入seata

在最外层服务pom.xml中,ctrl进入

复制代码
spring-cloud-alibaba-dependencies

在里面搜索

可见seata的版本是2.1.0所以启动seata服务端一定要用2.1.0

复制下面的alibaba的seata,注意不是springboot的

复制代码
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
        <version>2023.0.3.2</version>
      </dependency>

在服务最外层service模块下的pom.xml引入

不用写版本号

引入之后在maven依赖中可以看到已经有了

3.服务文件引入

可以配置每个服务的yml用于指定分组

但也可以不在yml配,默认为

复制代码
default_tx_group,因为如下有默认组

添加file.conf文件,以后也可以放到nacos里面

复制代码
service {
  #transaction service group mapping  default_tx_group是默认分组
  vgroupMapping.default_tx_group = "default"
  #only support when registry.type=file, please don't set multiple addresses
  #注意不是seara网页端口
  default.grouplist = "127.0.0.1:8091"
  #degrade, current not support
  enableDegrade = false
  #disable seata
  disableGlobalTransaction = false
}

4.标注全局事务

@GlobalTransactional

也就是需要配置TM,它是入口

复制代码
package com.atguigu.business.service.impl;

import com.atguigu.business.feign.OrderFeignClient;
import com.atguigu.business.feign.StorageFeignClient;
import com.atguigu.business.service.BusinessService;
import org.apache.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
public class BusinessServiceImpl implements BusinessService {

    //第一步就是拿到远程服务客户端
    @Autowired
    StorageFeignClient storageFeignClient;

    @Autowired
    OrderFeignClient orderFeignClient;
@GlobalTransactional
    @Override
    public void purchase(String userId, String commodityCode, int orderCount) {
        //TODO 1. 扣减库存
        storageFeignClient.deduct(commodityCode,orderCount);
        //TODO 2. 创建订单
        orderFeignClient.create(userId,commodityCode,orderCount);
    }
}

四种事务模式

默认是AT模式,就是自动模式

XA模式:

使用早期数据库模式,第一阶段提交就没有真正提交, 一直占用数据库,阻塞等待

更改方法

TCC

全手动,适合于夹杂了非数据库事务,也就是广义的事务,比如发邮件,发短信

要额外写接口这三个阶段(准备,提交,回滚)要做什么

比如第一阶段已经发了短信,只能再第三阶段再发一个纠正短信了

Saga

长事务

可能要好多天,比如请假,要经过审批,就不适合于用锁了

基于消息队列,第二个人收到第一个人的消息再做事,某个人失败了就通知所有人失败了

其他人收到消息后使用自定义处理,也就是补偿代码

其它

1.配置输出为null

order.timeout=null;order.auto-confirm=nullorder.db-urlnull

原因

proerties:

复制代码
#spring.cloud.nacos.discovery.server-addr=localhost:8848

yml

没用discovery

复制代码
server:
  port:8900
spring:
  application:
    name: service-order
  cloud:
    nacos:
        server-addr: localhost:8848
        config:
          namespace: dev
  config:
    import:
      - nacos:common.properties?group=order
      - nacos:db.properties?group=order

日志

给微服务配置远程日志

在每个服务的application.yml中给feign包

复制代码
logging:
  level:
    com.i7i8i9.feign: debug
复制代码
#注意:远程配置的优先级高于本地

server:
  port:8900    #虽然这里写了8090,但是实际使用端口还是可以在Edit configurattion中指定
spring:
  profiles:
    active: uat       #第1步: 指定本项目激活环境,该名字需要对应nacos的namespace
    include: feign      #包含yml标识 feign,也就是application-feign.yml
  application:
    name: service-order
  cloud:
    nacos:
        server-addr: localhost:8848
        config:
          namespace: ${spring.profiles.active:dev}   #获取激活环境名称,找到nacos同名命名空间,如果获取不到环境名称就使用冒号后面的默认值
#          :dev是默认值dev的意思,如果找不到这个变量
logging:
  level:
    com.i7i8i9.feign: debug





---
spring:               #on-profile: dev 也就是说dev需要启用的配置,每个环境要导入的不一定一样
  config:
    import:
      - nacos:common.properties?group=order
      - nacos:db.properties?group=order
    activate:
      on-profile: dev


---
spring:               #on-profile: UAT 也就是说dev需要启用的配置,每个环境要导入的不一定一样
  config:
    import:
      - nacos:common.properties?group=order
      - nacos:db.properties?group=order
    activate:
      on-profile: uat

---
spring:           #on-profile: prod 也就是说dev需要启用的配置,每个环境要导入的不一定一样
  config:
    import:
      - nacos:common.properties?group=order
      - nacos:db.properties?group=order
    activate:
      on-profile: prod

然后在微服务的配置类里面把Level放到容器中(就是加上@Bean)

复制代码
package com.i7i8i9.config;

import feign.Logger;
import feign.RetryableException;
import feign.Retryer;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class OrderConfig {

//    @Bean
   Retryer retryer(){
       return new Retryer.Default();
   }


    @Bean
    Logger.Level  feignLoggerLevel(){
        return  Logger.Level.FULL;
    }



    @LoadBalanced   //注解式负载均衡,不要难过其他操作
    @Bean
    RestTemplate restTemplate(){
        return new RestTemplate();
    }



}

注释

idea创建java类时自动配置注解 idea如何设置类的自动注释_mob64ca1415f0ab的技术博客_51CTO博客

前端

Vue3与ts中使用axios vue3加ts_mob64ca14031c97的技术博客_51CTO博客

Debug

1.seata两段事务debug

标注断点

全部服务都以debug模式启动

发送请求

刷新seata

可见因为标记了@GlobalTransactional出现一个全局事务

applicationId就是所属应用: seata-business

transactionName触发全局事务入口 purchase(java.lang.String, java.lang.String, int)

status:beigin

timeout: 1分钟没做完就过期

还可以点击最后面查看用到了哪些全局锁(每个服务修改自己数据前获得的,以保证别的服务不能穿插着改)

放行

报错

指向扣库存,原因是库存分支事务注册失败,超过了上述配置的60s导致

重新来

重新发送请求,再加个断点

放行

就会来到第二个断点

打开最右侧的包括分支事务

就可以查看分支事务,是已经注册完了的库存事务

全局锁也能看到信息

可以看到在数据表storage_tbl有一把全局锁

去storage_db数据库查看

数据此时是98

并且有undo日志

数据复制出来

复制代码
{"@class":"org.apache.seata.rm.datasource.undo.BranchUndoLog","xid":"192.168.32.1:8091:9628920695037968","branchId":9628920695037969,"sqlUndoLogs":["java.util.ArrayList",

[{"@class":"org.apache.seata.rm.datasource.undo.SQLUndoLog","sqlType":"UPDATE","tableName":"storage_tbl","beforeImage":
{"@class":"org.apache.seata.rm.datasource.sql.struct.TableRecords","tableName":"storage_tbl","rows":["java.util.ArrayList",
[{"@class":"org.apache.seata.rm.datasource.sql.struct.Row","fields":["java.util.ArrayList",
[{"@class":"org.apache.seata.rm.datasource.sql.struct.Field","name":"count","keyType":"NULL","type":4,"value":100},
{"@class":"org.apache.seata.rm.datasource.sql.struct.Field","name":"id","keyType":"PRIMARY_KEY","type":4,"value":1}]]}]]},"afterImage":
{"@class":"org.apache.seata.rm.datasource.sql.struct.TableRecords","tableName":"storage_tbl","rows":["java.util.ArrayList",
[{"@class":"org.apache.seata.rm.datasource.sql.struct.Row","fields":["java.util.ArrayList",
[{"@class":"org.apache.seata.rm.datasource.sql.struct.Field","name":"count","keyType":"NULL","type":4,"value":98},
{"@class":"org.apache.seata.rm.datasource.sql.struct.Field","name":"id","keyType":"PRIMARY_KEY","type":4,"value":1}]]}]]}}]]}

有before镜像

有after镜像

目的就是为了恢复

保存订单处设置断点

因为订单设置了一定会失败,所以可以看到account和storage都undo_log

两个子事务

两个全局锁

相关推荐
西岸行者4 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意4 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码4 天前
嵌入式学习路线
学习
毛小茛4 天前
计算机系统概论——校验码
学习
babe小鑫4 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms4 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下4 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。4 天前
2026.2.25监控学习
学习
im_AMBER4 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J4 天前
从“Hello World“ 开始 C++
c语言·c++·学习