springboot+nacos+seata1.4实现分布式事务

版本:
 Springboot:2.2.0
 SpringCloud: 2020.0.3
 Seata: 1.4

本文章demo地址:https://gitee.com/TZWw/springboot-nacos-seata14

1. 下载seata

1)地址:http://seata.io/zh-cn/blog/download.html
√
2)在conf文件夹修改file.conf文件
在这里插入图片描述

3)向本地数据库导入seata需要的表

  • 创建名字为seata的数据库
  • 新建表branch_table、global_table、lock_table

CREATE TABLE branch_table (
branch_id bigint NOT NULL,
xid varchar(128) NOT NULL,
transaction_id bigint DEFAULT NULL,
resource_group_id varchar(32) DEFAULT NULL,
resource_id varchar(256) DEFAULT NULL,
lock_key varchar(128) DEFAULT NULL,
branch_type varchar(8) DEFAULT NULL,
status tinyint DEFAULT NULL,
client_id varchar(64) DEFAULT NULL,
application_data varchar(2000) DEFAULT NULL,
gmt_create datetime DEFAULT NULL,
gmt_modified datetime DEFAULT NULL,
PRIMARY KEY (branch_id),
KEY idx_xid (xid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

CREATE TABLE global_table (
xid varchar(128) NOT NULL,
transaction_id bigint DEFAULT NULL,
status tinyint NOT NULL,
application_id varchar(32) DEFAULT NULL,
transaction_service_group varchar(32) DEFAULT NULL,
transaction_name varchar(128) DEFAULT NULL,
timeout int DEFAULT NULL,
begin_time bigint DEFAULT NULL,
application_data varchar(2000) DEFAULT NULL,
gmt_create datetime DEFAULT NULL,
gmt_modified datetime DEFAULT NULL,
PRIMARY KEY (xid),
KEY idx_gmt_modified_status (gmt_modified,status),
KEY idx_transaction_id (transaction_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

CREATE TABLE lock_table (
row_key varchar(128) NOT NULL,
xid varchar(96) DEFAULT NULL,
transaction_id mediumtext,
branch_id mediumtext,
resource_id varchar(256) DEFAULT NULL,
table_name varchar(32) DEFAULT NULL,
pk varchar(36) DEFAULT NULL,
gmt_create datetime DEFAULT NULL,
gmt_modified datetime DEFAULT NULL,
PRIMARY KEY (row_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

seata数据库
4)修改registry.conf文件
在这里插入图片描述
在这里插入图片描述
5)将seata配置信息添加到nacos配置中心

1.启动本地的nacos服务
2.下载config.txt和nacos-config.sh两个文件
https://github.com/seata/seata/blob/develop/script/config-center/config.txt
https://github.com/seata/seata/blob/develop/script/config-center/nacos/nacos-config.sh
3.然后执行nacos-config.sh脚本

在这里插入图片描述

4.查看nacos中添加成功的配置

在这里插入图片描述

6)启动seata

进入bin目录下,执行
./seata-server.sh
出现下图即为启动成功

在这里插入图片描述

2. 服务间调用(服务one调用服务two)

1)创建one和two数据库,每个数据库都必须包含undo_log表

  • one数据库

CREATE TABLE count (
id int NOT NULL AUTO_INCREMENT,
count int DEFAULT NULL COMMENT ‘库存’,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb3;

CREATE TABLE undo_log (
id bigint NOT NULL AUTO_INCREMENT,
branch_id bigint NOT NULL,
xid varchar(100) NOT NULL,
context varchar(128) NOT NULL,
rollback_info longblob NOT NULL,
log_status int 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=20 DEFAULT CHARSET=utf8mb3;

  • two数据库

CREATE TABLE order (
id int NOT NULL AUTO_INCREMENT,
order_count int DEFAULT NULL,
product_id bigint DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb3;

CREATE TABLE undo_log (
id bigint NOT NULL AUTO_INCREMENT,
branch_id bigint NOT NULL,
xid varchar(100) NOT NULL,
context varchar(128) NOT NULL,
rollback_info longblob NOT NULL,
log_status int 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=3 DEFAULT CHARSET=utf8mb3;

在这里插入图片描述
2) 创建one和two服务

此处省略创建服务过程。。。

在这里插入图片描述

maven父工程依赖

<?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>
    <packaging>pom</packaging>
    <modules>
        <module>serviceone</module>
        <module>servicetwo</module>
<!--        common是公共类-->
        <module>servicecommon</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo2</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>2020.0.3</spring-cloud.version>
        <spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.9</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <version>2.3.3.RELEASE</version>
                <scope>test</scope>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.2.0</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-context</artifactId>
                <version>2.2.3.RELEASE</version>
            </dependency>


            <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>2021.1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.26</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-log4j -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-log4j</artifactId>
                <version>1.3.8.RELEASE</version>
            </dependency>

        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

  • one服务:

bootstrap.yml文件

# Spring
spring:
  application:
    # 应用名称
    name: service-one
  profiles:
    # 环境配置
    active: dev
  main:
    allow-bean-definition-overriding: true
  cloud:
    nacos:
      discovery:
        # 服务注册地址
        server-addr: localhost:8848
#        namespace: 3d25ad9f-6b5a-4f1a-a4a7-0bbba90a00fa
        group: SEATA_GROUP
      config:
        # 配置中心地址
        server-addr: localhost:8848
        namespace: 8221aa53-c648-4c6a-8a41-0c3a685ba58e
#        # 配置文件格式
        file-extension: yml
  #        # 共享配置
#        shared-dataids: application-${
    
    spring.profiles.active}.${
    
    spring.cloud.nacos.config.file-extension}
#
seata:
  tx-service-group: my_test_tx_group
  registry:
    type: nacos
    nacos:
      server-addr: ${
    
    spring.cloud.nacos.discovery.server-addr}
      group: ${
    
    spring.cloud.nacos.discovery.group}
  #      namespace: 6c990727-93b2-4081-a8c6-6b015c56eda2
  config:
    type: nacos
    nacos:
      server-addr: ${
    
    spring.cloud.nacos.discovery.server-addr}
      group: ${
    
    spring.cloud.nacos.discovery.group}
#      namespace: 6db428d4-e7a3-4dd3-be02-283960e0e704
  service:
    vgroup-mapping:
      my_test_tx_group: default

在这里插入图片描述

nacos中one的配置(service-one-dev.yml):

# Spring
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/service-one?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
    username: root
    password: 123456789

server:
  port: 8085

# Mybatis配置
mybatis:
    # 配置mapper的扫描,找到所有的mapper.xml映射文件
    mapperLocations: classpath:mapper/**/*.xml

# 我使用的这个版本这一步可以忽略
httpclient:
  enabled: true

one服务依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>

        <!--nacos-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-nacos-config -->
        <!--  不配置无法读取nacos配置      -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
        </dependency>
        <!-- 升级spring cloud版本之后发现bootstrap.yml 失效了,阅读官方文档得知,需要新增一个引用来开启bootstrap.xml文件的读取,
        新版spring cloud默认是关闭读取了。-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
        <!-- 不引入,bootstrap.yml无法使用       -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-context</artifactId>
            <version>3.0.2</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- 添加feign       -->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.6.6</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.6</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
        </dependency>
        <!-- 在 pom 中添加依賴,解决使用get方式请求时出现的Request method 'POST' not supported-->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>
    </dependencies>

controller :

    @GetMapping("/insertOpt")
    public CommonResult insertOpt() {
    
    
        try {
    
    
            countService.insertOpt();
            return new CommonResult(true, "成功", null);
        } catch (Exception e) {
    
    
            return new CommonResult(false, "失败", null);
        }
    }

serviceImpl

 	@Override
    @GlobalTransactional(rollbackFor = Exception.class, name = "insertOpt")
    public CommonResult insertOpt() {
    
    
        Count count = new Count();
        count.setCount(12);
        int insert = this.countDao.insert(count);
        if (insert == 0) {
    
    
            throw new RuntimeException("first失败");
        }
        Order order = new Order();
        order.setOrderCount(12);
        order.setProductId(12L);
        CommonResult commonResult = remoteServiceTwo.insertOne(order);
        if (!commonResult.getBool()){
    
    
            throw new RuntimeException("操作远程失败!");
        }
        Map<String, Object> map = new HashMap<>(16);
        map.put("count", insert);
        map.put("order", commonResult);
        System.err.println("map===="+ map.toString());
        return new CommonResult(true, "成功", map);
    }

feign请求

@FeignClient(value = "service-two")
public interface RemoteServiceTwo {
    
    

    @PostMapping("/order/insertOne")
    public CommonResult insertOne(Order order);

}
  • two服务

bootstrap.yml

# Spring
spring:
  application:
    # 应用名称
    name: service-two
  profiles:
    # 环境配置
    active: dev
  main:
    allow-bean-definition-overriding: true
  cloud:
    nacos:
      discovery:
        # 服务注册地址
        server-addr: localhost:8848
#        namespace: 3d25ad9f-6b5a-4f1a-a4a7-0bbba90a00fa
        group: SEATA_GROUP
      config:
        # 配置中心地址
        server-addr: localhost:8848
        namespace: 8221aa53-c648-4c6a-8a41-0c3a685ba58e
#        # 配置文件格式
        file-extension: yml
#        # 共享配置
#        shared-dataids: application-${
    
    spring.profiles.active}.${
    
    spring.cloud.nacos.config.file-extension}


seata:
  tx-service-group: my_test_tx_group
  registry:
    type: nacos
    nacos:
      server-addr: ${
    
    spring.cloud.nacos.discovery.server-addr}
      group: ${
    
    spring.cloud.nacos.discovery.group}
  #      namespace: 6c990727-93b2-4081-a8c6-6b015c56eda2
  config:
    type: nacos
    nacos:
      server-addr: ${
    
    spring.cloud.nacos.discovery.server-addr}
      group: ${
    
    spring.cloud.nacos.discovery.group}
  service:
    vgroup-mapping:
      my_test_tx_group: default


pom.xml 依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>

        <!--nacos-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-nacos-config -->
        <!--  不配置无法读取nacos配置      -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
        </dependency>
        <!-- 升级spring cloud版本之后发现bootstrap.yml 失效了,阅读官方文档得知,需要新增一个引用来开启bootstrap.xml文件的读取,
        新版spring cloud默认是关闭读取了。-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>



        <!-- 不引入,bootstrap.yml无法使用       -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-context</artifactId>
            <version>3.0.2</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- 添加feign       -->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.6.6</version>
        </dependency>

        <dependency>
            <groupId>com.example</groupId>
            <artifactId>servicecommon</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.6</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-log4j -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j</artifactId>
        </dependency>

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


    </dependencies>

nacos中two服务的配置service-two-dev.yml

# Spring
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/service-two?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
    username: root
    password: 123456789

server:
  port: 8086

# Mybatis配置
mybatis:
    # 配置mapper的扫描,找到所有的mapper.xml映射文件
    mapperLocations: classpath:mapper/**/*.xml

# 我使用的这个版本这一步可以忽略
httpclient:
  enabled: true

two服务controller

    @PostMapping("insertOne")
    public CommonResult selectOne(@RequestBody Order order) {
    
    
        try {
    
    
            this.orderService.insert(order);
            return new CommonResult(true, "成功", null);
        } catch (Exception e) {
    
    
            StaticLog.error("失败:======{}", e);
            return new CommonResult(false, "失败", null);
        }
    }

serviceImpl

    /**
     * 新增数据
     *
     * @param order 实例对象
     * @return 实例对象
     */
    @Override
    public Order insert(Order order) {
    
    
        // int a = 1/0;  // 此处是为了出现错误,看seata是否会回滚
        this.orderDao.insert(order);
        return order;
    }

3. 查看结果

  • 插入成功操作

浏览器操作

在这里插入图片描述

serviceone的日志

在这里插入图片描述

servicetwo日志

在这里插入图片描述

数据库结果-插入成功 (清空数据库进行插入失败操作)

在这里插入图片描述

  • 插入失败操作
    1) 插入失败,进行回滚—在servicetwo业务代码上添加一个报错代码

在这里插入图片描述

浏览器操作

在这里插入图片描述

serviceone 日志(进行了回滚)

在这里插入图片描述

servicetwo 日志

在这里插入图片描述

数据库数据

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42551369/article/details/120455101
今日推荐