Seata AT分布式事務(wù)簡(jiǎn)單集成

Seata 是什么?

Seata 是一款開源的分布式事務(wù)解決方案,致力于提供高性能和簡(jiǎn)單易用的分布式事務(wù)服務(wù)。Seata 將為用戶提供了 AT、TCC、SAGA 和 XA 事務(wù)模式,為用戶打造一站式的分布式解決方案。
關(guān)于Seata的介紹和事務(wù)的詳細(xì)流轉(zhuǎn)細(xì)節(jié)參考 Seata官網(wǎng)

本文采用docker部署seata服務(wù)
1、運(yùn)行鏡像

docker run --name seata-server -p 8091:8091 -d seataio/seata-server

2、復(fù)制配置文件到主機(jī) 當(dāng)前目錄

docker cp seata-server:/seata-server .

3、停止服務(wù)

docker stop seata-server

4、刪除服務(wù)

docker rm seata-server

5、重新運(yùn)行服務(wù)
# 腳本
# BEGIN ANSIBLE MANAGED BLOCK
#!/bin/bash
HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
docker rm -f seata-server;
docker run --name seata-server \
  --restart=always \
  -v $HOME/seata-server:/seata-server \
  -e SEATA_IP=192.168.8.43 \
  -e SEATA_PORT=8091 \
  -p 8091:8091 \
  -d seataio/seata-server
# END ANSIBLE MANAGED BLOCK
6、切換到seata配置文件目錄

cd /seata-server/resources
修改register.conf

  • 如果是配置中心是file的話,會(huì)使用file.conf里面的配置,如果是其他,使用配置中心的配置
  • 直連 eureka/consul/apollo/etcd/zookeeper/sofa/redis/file
本文采用nacos配置
  • 修改 register.type 和 config.type 為 nacos
    然后修改nacos的相關(guān)配置
# 注冊(cè)中心配置
registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "nacos" # 注冊(cè)類型
  loadBalance = "RandomLoadBalance"
  loadBalanceVirtualNodes = 10

  nacos {
    application = "seata-server-lss"
    serverAddr = "123.57.26.81:8848"
    group = "SEATA_GROUP"
    namespace = "lss_test"
    cluster = "default"
    username = "nacos"
    password = "nacos"
  }
}
# 配置中心配置
config {
  # file、nacos 、apollo、zk、consul、etcd3
  type = "nacos"

  nacos {
    serverAddr = "123.57.26.81:8848"
    namespace = "lss_test"
    group = "SEATA_GROUP"
    username = "nacos"
    password = "nacos"
    dataId = "seataServer.properties"
  }
}
7、重啟seata-server

docker restart seata-server
查看nacos,發(fā)現(xiàn)seata 服務(wù)端已正常啟動(dòng)

image.png

接下來配置項(xiàng)目

參考seata官網(wǎng)的賬戶、訂單項(xiàng)目

1、新建項(xiàng)目,如下圖
image.png
2、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">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
<!--        <relativePath />-->
<!--        <groupId>org.lss</groupId>-->
<!--        <artifactId>project</artifactId>-->
<!--        <version>1.0.0</version>-->
    </parent>


    <groupId>com.lss</groupId>
    <artifactId>seata_xa</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>

    <properties>
        <seata.version>1.4.0</seata.version>
        <alibaba.cloud.version>2.2.3.RELEASE</alibaba.cloud.version>
    </properties>

    <modules>
        <module>business_xa</module>
        <module>order_xa</module>
        <module>account_xa</module>
    </modules>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--  lombok依賴 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
        </dependency>
        <!-- durid -->
<!--        <dependency>-->
<!--            <groupId>com.alibaba</groupId>-->
<!--            <artifactId>druid-spring-boot-starter</artifactId>-->
<!--            <version>1.1.10</version>-->
<!--        </dependency>-->
        <!--nacos動(dòng)態(tài)加載配置-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!--nacos服務(wù)注冊(cè)發(fā)現(xiàn)-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!-- seata 引入此依賴才能成功-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
        <!--   由于版本問題,需要排除以下依賴  -->
            <exclusions>
                <exclusion>
                    <groupId>io.seata</groupId>
                    <artifactId>seata-spring-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
<!--        <dependency>-->
<!--            <groupId>com.alibaba.cloud</groupId>-->
<!--            <artifactId>spring-cloud-alibaba-seata</artifactId>-->
<!--            <version>2.0.0.RELEASE</version>-->
<!--            <exclusions>-->
<!--                <exclusion>-->
<!--                    <groupId>io.seata</groupId>-->
<!--                    <artifactId>seata-all</artifactId>-->
<!--                </exclusion>-->
<!--            </exclusions>-->
<!--        </dependency>-->
        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
            <version>${seata.version}</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!-- feign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>

        <!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.48</version>
<!--            <scope>runtime</scope>-->
        </dependency>
        <!-- jdbc -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR8</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${alibaba.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>
3、config.txt 和 nacos-config.sh是從 官網(wǎng) 拷出來的配置,需要上傳到nacos,具體也可參考/seata-server/resources/README-zh.md 里面的描述
  • nacos-init.sh 是運(yùn)行 nacos-config.sh 的腳本

#-h: host, the default value is localhost.
#
#-p: port, the default value is 8848.
#
#-g: Configure grouping, the default value is 'SEATA_GROUP'.
#
#-t: Tenant information, corresponding to the namespace ID field of Nacos, the default value is ''.
#
#-u: username, nacos 1.2.0+ on permission control, the default value is ''.
#
#-w: password, nacos 1.2.0+ on permission control, the default value is ''.

bash nacos-config.sh -h 123.57.26.81 -p 8848 -g SEATA_GROUP -t lss_test -u nacos -w nacos

執(zhí)行后 bash nacos-init.sh 后,在nacos上可查看到相關(guān)配置

image.png

項(xiàng)目整體結(jié)構(gòu)圖

image.png
4、business_xa項(xiàng)目
  • bootstrap.yml
server:
  port: 17000

nacos:
  namespace: lss_test
  address: 123.57.26.81:8848

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/xa_order?useSSL=false&serverTimezone=UTC
    username: root
    password: 12345678
    driver-class-name: com.mysql.jdbc.Driver
  application:
    name: business_xa
  cloud:
    nacos:
      namespace: ${nacos.namespace}
      server-addr: ${nacos.address}
      config:
        enabled: true
        namespace: ${spring.cloud.nacos.namespace}
#          file-extension: yml
#          shared-configs:
#            - data-id: common.yml
#              refresh: true
      discovery:
        enabled: true
        namespace: ${spring.cloud.nacos.namespace}
        register-enabled: true

# seata 配置
seata:
  # 注冊(cè)信息
  registry:
    type: nacos
    nacos:
      application: seata-server-lss   # 這個(gè)是 seata 服務(wù)端的應(yīng)用名稱
      server-addr: ${nacos.address}  # nacos 服務(wù)地址
      group : "SEATA_GROUP"           # nacos 分組
      namespace: ${nacos.namespace}           # nacos 命名空間
      username: "nacos"
      password: "nacos"
  # 配置信息
  config:
    type: nacos
    nacos:
      server-addr: 123.57.26.81:8848
      group: "SEATA_GROUP"
      namespace: ${nacos.namespace}
      username: "nacos"
      password: "nacos"
  application-id: ${spring.application.name}
  tx-service-group: seata-server_xa_test    # 自定義事物組 tc
  • BusinessController.java
package com.lss.sample.operator;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("api")
@RestController
@Slf4j
public class BusinessController {


    @Autowired
    BusinessService businessService;

    @GetMapping("purchase")
    public String purchase(@RequestParam(value = "type", defaultValue = "1") Integer type ) {

        try {
            businessService.purchase(type);
        } catch (Exception exx) {
            log.info("異常:{}", exx);
            return "Purchase Failed:" + exx.getMessage();
        }
        return "SUCCESS";
    }
}
  • BusinessService.java
package com.lss.sample.operator;

import com.lss.sample.feign.AccountFeignClient;
import com.lss.sample.feign.OrderFeignClient;
import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class BusinessService {

    final String SUCCESS = "SUCCESS";

    @Autowired
    private OrderFeignClient orderFeignClient;

    @Autowired
    AccountFeignClient accountFeignClient;

    @GlobalTransactional(rollbackFor = Exception.class)
    public void purchase(Integer type) {
        String xid = RootContext.getXID();
        log.info("business-xid:{}", xid);


        String accountResult = accountFeignClient.add();
        throw new RuntimeException("賬戶服務(wù)調(diào)用失敗,事務(wù)回滾!");

        if (!SUCCESS.equals(accountResult)) {
            throw new RuntimeException("賬戶服務(wù)調(diào)用失敗,事務(wù)回滾!");
        }else {
            log.info("賬戶服務(wù)調(diào)用成功...");
        }
//
        String orderResult = orderFeignClient.create(type);

        if (!SUCCESS.equals(orderResult)) {
            log.info("訂單服務(wù)調(diào)用失敗...");
            throw new RuntimeException("訂單服務(wù)調(diào)用失敗,事務(wù)回滾!");
        }else {
            log.info("訂單服務(wù)調(diào)用成功...");
        }
    }
}
  • AccountFeignClient.java
package com.lss.sample.feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient(name = "AccountFeignClient", url = "127.0.0.1:17002")
public interface AccountFeignClient {

    @GetMapping("api/add")
    String add();
}

  • OrderFeignClient.java
package com.lss.sample.feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(name = "OrderFeignClient", url = "127.0.0.1:17001")
public interface OrderFeignClient {

    @GetMapping("api/create")
    String create(@RequestParam(value = "type") Integer type);

}
  • 啟動(dòng)類 BusinessXAApplication.java
package com.lss.sample;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

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

5、account_xa項(xiàng)目
  • account_xa服務(wù)的bootstrap.yml
server:
  port: 17002

nacos:
  namespace: lss_test
  address: 123.57.26.81:8848

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/xa_account?useSSL=false&serverTimezone=UTC
    username: root
    password: 12345678
#    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
  application:
    name: account_xa
  cloud:
    nacos:
      namespace: ${nacos.namespace}
      server-addr: ${nacos.address}
      config:
        enabled: true
        namespace: ${spring.cloud.nacos.namespace}
#          file-extension: yml
#          shared-configs:
#            - data-id: common.yml
#              refresh: true
      discovery:
        enabled: true
        namespace: ${spring.cloud.nacos.namespace}
        register-enabled: true

# seata 配置
seata:
  # 注冊(cè)信息
  registry:
    type: nacos
    nacos:
      application: seata-server-lss   # 這個(gè)是 seata 服務(wù)端的應(yīng)用名稱
      server-addr: ${nacos.address}  # nacos 服務(wù)地址
      group : "SEATA_GROUP"           # nacos 分組
      namespace: ${nacos.namespace}           # nacos 命名空間
      username: "nacos"
      password: "nacos"
  # 配置信息
  config:
    type: nacos
    nacos:
      server-addr: 123.57.26.81:8848
      group: "SEATA_GROUP"
      namespace: ${nacos.namespace}
      username: "nacos"
      password: "nacos"
  application-id: ${spring.application.name}
  tx-service-group: seata-server_xa_test    # 自定義事物組 tc
  • AccountController.java
package com.lss.sample.operator;

import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("api")
@Slf4j
public class AccountController {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @GetMapping("add")
    public String add() {
        String xid = RootContext.getXID();
        log.info("account-xid:{}", xid);
        jdbcTemplate.update("update account set account = 10000 where id = 4 ");
        return "SUCCESS";
    }
}

  • DataSourceConfig.java
package com.lss.sample.config;

import com.alibaba.druid.pool.DruidDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import io.seata.rm.datasource.xa.DataSourceProxyXA;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

@Configuration
public class DataSourceConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DruidDataSource druidDataSource() {
        return new DruidDataSource();
    }

    @Bean("dataSourceProxy")
    public DataSource dataSource(DruidDataSource druidDataSource) {
        // DataSourceProxy for AT mode
//         return new DataSourceProxy(druidDataSource);

        // DataSourceProxyXA for XA mode
        return new DataSourceProxyXA(druidDataSource);
    }

    @Bean("jdbcTemplate")
    public JdbcTemplate jdbcTemplate(DataSource dataSourceProxy) {
        return new JdbcTemplate(dataSourceProxy);
    }
}
  • 啟動(dòng)類 AccountXAApplication
package com.lss.sample;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@SpringBootApplication
@EnableFeignClients
@EnableTransactionManagement
public class AccountXAApplication {
    public static void main(String[] args) {
        SpringApplication.run(AccountXAApplication.class, args);
    }
}
6、order_xa項(xiàng)目
  • bootstrap.yml
server:
  port: 17001

nacos:
  namespace: lss_test
  address: 123.57.26.81:8848

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/xa_order?useSSL=false&serverTimezone=UTC
    username: root
    password: 12345678
    driver-class-name: com.mysql.jdbc.Driver
  application:
    name: order_xa
  cloud:
    nacos:
      namespace: ${nacos.namespace}
      server-addr: ${nacos.address}
      config:
        enabled: true
        namespace: ${spring.cloud.nacos.namespace}
#          file-extension: yml
#          shared-configs:
#            - data-id: common.yml
#              refresh: true
      discovery:
        enabled: true
        namespace: ${spring.cloud.nacos.namespace}
        register-enabled: true

# seata 配置
seata:
  # 注冊(cè)信息
  registry:
    type: nacos
    nacos:
      application: seata-server-lss   # 這個(gè)是 seata 服務(wù)端的應(yīng)用名稱
      server-addr: ${nacos.address}  # nacos 服務(wù)地址
      group : "SEATA_GROUP"           # nacos 分組
      namespace: ${nacos.namespace}           # nacos 命名空間
      username: "nacos"
      password: "nacos"
  # 配置信息
  config:
    type: nacos
    nacos:
      server-addr: 123.57.26.81:8848
      group: "SEATA_GROUP"
      namespace: ${nacos.namespace}
      username: "nacos"
      password: "nacos"
  application-id: ${spring.application.name}
  tx-service-group: seata-server_xa_test    # 自定義事物組 tc
  • OrderController.java
package com.lss.sample.operator;

import io.seata.core.context.RootContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("api")
@RestController
@Slf4j
public class OrderController {

    @Autowired
    JdbcTemplate jdbcTemplate;

    @GetMapping("create")
    public String create(@RequestParam(value = "type") Integer type) {

        String xid = RootContext.getXID();
        log.info("account-xid:{}", xid);
        try {
            deal(type);
        } catch (Exception e) {
            return "FAIL";
        }
        return "SUCCESS";
    }
    @Transactional
    public void deal(Integer type) {
        jdbcTemplate.update("update `order` set num = 100 where id = 1 ");
        if (type.equals(2)) {
            log.info("order 調(diào)用異常...");
            throw new RuntimeException("order 調(diào)用異常...");
        }

    }
}
  • DataSourceConfig
package com.lss.sample.config;

import com.alibaba.druid.pool.DruidDataSource;
import io.seata.rm.datasource.xa.DataSourceProxyXA;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

@Configuration
public class DataSourceConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DruidDataSource druidDataSource() {
        return new DruidDataSource();
    }

    @Bean("dataSourceProxy")
    public DataSource dataSource(DruidDataSource druidDataSource) {
        // DataSourceProxy for AT mode
//         return new DataSourceProxy(druidDataSource);

        // DataSourceProxyXA for XA mode
        return new DataSourceProxyXA(druidDataSource);
    }

    @Bean("jdbcTemplate")
    public JdbcTemplate jdbcTemplate(DataSource dataSourceProxy) {
        return new JdbcTemplate(dataSourceProxy);
    }
}
  • 啟動(dòng)類OrderXAApplication.java
package com.lss.sample;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

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

運(yùn)行項(xiàng)目

1、business_xa、account_xa、order_xa依次運(yùn)行后,在nacos上發(fā)現(xiàn)項(xiàng)目都已經(jīng)注冊(cè)上去了,但是項(xiàng)目會(huì)報(bào)一個(gè)錯(cuò)誤

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

報(bào)錯(cuò)原因在這個(gè)類里 io.seata.core.rpc.netty.NettyClientChannelManager
根據(jù)seata導(dǎo)入客戶端相關(guān)配置后
添加一個(gè)配置

  • service.vgroupMapping.(自定義的事務(wù)組名稱 tc)=default 就可以了
    本文的配置為: service.vgroupMapping.seata-server_xa_test = default
    nacos上如下圖
    image.png
2、在數(shù)據(jù)庫(kù)中添加sql腳本
  • xa_account 庫(kù)
DROP TABLE IF EXISTS `account`;
CREATE TABLE `account` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `account` varchar(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4;


DROP TABLE IF EXISTS `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=12 DEFAULT CHARSET=utf8;
  • xa_order 庫(kù)
DROP TABLE IF EXISTS `order`;
CREATE TABLE `order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `num` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

DROP TABLE IF EXISTS `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=12 DEFAULT CHARSET=utf8;
3、至此,seata集成已經(jīng)完成了,啟動(dòng)項(xiàng)目后,訪問business_xa服務(wù)

curl http://localhost:17000/api/purchase?type=1
發(fā)現(xiàn)數(shù)據(jù)庫(kù)數(shù)據(jù)被正常更新
重新手動(dòng)更新數(shù)據(jù)后,再次訪問
curl http://localhost:17000/api/purchase?type=2
發(fā)現(xiàn)數(shù)據(jù)庫(kù)數(shù)據(jù)回滾

集成過程可能還會(huì)有其他的問題,本文已經(jīng)盡可能寫到了,希望對(duì)你學(xué)習(xí)seata有所幫助
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容