Spring Cloud alibaba——seata的配置与使用

什么是seata?

Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。

核心特性

高性能:基于异步执行和零拷贝设计,提供高吞吐量
易用性:提供简单易用的注解和API
多种模式:支持AT、TCC、Saga、XA等多种事务模式
微服务友好:无缝集成Spring Cloud、Dubbo等微服务框架

核心概念

1. 角色组件

  • TC (Transaction Coordinator):事务协调器,维护全局事务的运行状态
  • TM (Transaction Manager):事务管理器,定义全局事务的范围
  • RM (Resource Manager):资源管理器,管理分支事务处理的资源

2. 事务模型

  • 全局事务:由TM定义,包含多个分支事务
  • 分支事务:由RM管理,是全局事务的组成部分
  • 事务组:具有相同事务组标识的资源集群
支持的事务模式
  • AT模式(Automatic Transaction)
  • TCC模式(Try-Confirm-Cancel)                                                                                             
  • Saga模式:适用于长事务场景,通过补偿机制实现最终一致性

绝大部分都是使用AT模式,所以本文也是针对于AT模式下的学习 

工作原理
  1. 事务开始:TM向TC申请开启全局事务
  2. 分支注册:RM向TC注册分支事务
  3. 事务执行:各分支事务执行业务逻辑
  4. 事务提交/回滚:TM根据执行结果决定提交或回滚全局事务
集成优势
  • 与Spring生态无缝集成
  • 支持多种注册中心和配置中心(Nacos、Eureka、Zookeeper等)
  • 提供多种数据源支持
  • 具备完善的监控和运维能力
  • Seata 有效地解决了微服务架构下的数据一致性问题,是构建可靠分布式系统的重要组件。 

seata-server的配置 

1.下载seata-server:

下载链接; https://github.com/seata/seata/releases

注意要根据自己cloud版本选择合适的版本,我的是如下版本:

2.创建seata数据库,执行sql文件:seata-2.0.0\script\server\db\mysql.sql

3. 修改配置文件: seata-2.0.0\script\config-center\config.txt

主要就是改这几个地方:数据库,redis,事务分组

这个是去除了一些不必要的配置的修改后的config.txt文件,自己复制修改对应数据,只需要改成自己的连接数据就可以了:

注意service.vgroupMapping.default_tx_group=default是设置默认事务分组,本配置的事务分组名为default_tx_group,后面会用到。

service.vgroupMapping.default_tx_group=default

store.mode=redis

store.redis.host=127.0.0.1
store.redis.port=6379
store.redis.maxConn=10
store.redis.minConn=1
store.redis.database=14
store.redis.queryLimit=100

#store.lock.mode=db
#store.session.mode=db
#store.publicKey=

store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&rewriteBatchedStatements=true
store.db.user=root
store.db.password=123456
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.distributedLockTable=distributed_lock
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000

#Transaction rule configuration, only for the server
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
server.distributedLockExpireTime=10000
server.xaerNotaRetryTimeout=60000
server.session.branchAsyncQueueSize=5000
server.session.enableBranchAsyncRemove=false

#Transaction rule configuration, only for the client
client.rm.asyncCommitBufferLimit=10000
client.rm.lock.retryInterval=10
client.rm.lock.retryTimes=30
client.rm.lock.retryPolicyBranchRollbackOnConflict=true
client.rm.reportRetryCount=5
client.rm.tableMetaCheckEnable=true
client.rm.tableMetaCheckerInterval=60000
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.rm.sagaJsonParser=fastjson
client.rm.tccActionInterceptorOrder=-2147482648
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.tm.defaultGlobalTransactionTimeout=60000
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
client.tm.interceptorOrder=-2147482648
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.onlyCareUpdateColumns=true
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
client.undo.logTable=undo_log
client.undo.compress.enable=true
client.undo.compress.type=zip
client.undo.compress.threshold=64k

#For TCC transaction mode
tcc.fence.logTableName=tcc_fence_log
tcc.fence.cleanPeriod=1h

#Log rule configuration, for client and server
log.exceptionRate=100

#Metrics configuration, only for the server
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898

transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableTmClientBatchSendRequest=false
transport.enableRmClientBatchSendRequest=true
transport.enableTcServerBatchSendResponse=false
transport.rpcRmRequestTimeout=30000
transport.rpcTmRequestTimeout=30000
transport.rpcTcRequestTimeout=30000
transport.threadFactory.bossThreadPrefix=NettyBoss
transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
transport.threadFactory.shareBossWorker=false
transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
transport.threadFactory.clientSelectorThreadSize=1
transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
transport.threadFactory.bossThreadSize=1
transport.threadFactory.workerThreadSize=default
transport.shutdown.wait=3
transport.serialization=seata
transport.compressor=none

 4.nacos配置中心添加seata-server.properties配置:

把上面config.text内容复制到seata-server.properties里面

5.修改application.yml文件: seata-2.0.0\conf\application.yml,自己将下面的nacos数据改成自己的,seata.config.nacos.namespace必须是seata-server.properties的同一个命名空间


server:
  port: 7091

spring:
  application:
    name: seata-server

logging:
  config: classpath:logback-spring.xml
  file:
    path: ${log.home:${user.home}/logs/seata}
  extend:
    logstash-appender:
      destination: 127.0.0.1:4560
    kafka-appender:
      bootstrap-servers: 127.0.0.1:9092
      topic: logback_to_logstash

console:
  user:
    username: seata
    password: seata
seata:
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848  # Nacos服务器地址
      namespace: "0f8cf46a-2f2b-4f43-934d-e4a511d47d91"                # 命名空间ID(可选)
      group: DEFAULT_GROUP           # 配置分组(可选)
      username: nacos              # Nacos用户名(可选)
      password: nacos              # Nacos密码(可选)
      data-id: seata-server.properties # 读取 nacos seata 配置
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848  # Nacos服务器地址
      namespace: "0f8cf46a-2f2b-4f43-934d-e4a511d47d91"                # 命名空间ID(可选)
      group: DEFAULT_GROUP           # 服务注册分组(可选)
      cluster: default
      username: nacos              # Nacos用户名(可选)
      password: nacos              # Nacos密码(可选)
  security:
    secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
    tokenValidityInMilliseconds: 1800000
    ignore:
      urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login,/metadata/v1/**

注意:

6.启动seata-server服务:双击 seata-server.bat文件

 

 启动成功:

访问seata:http://127.0.0.1:7091/,用户/密码就是上面配置文件里面配置的seata/seata

注意:上面seata是配置了redis的,记住要启动redis 

seata的简单运用 

我们通过创建订单扣减库存的例子来简单学习一下seata的使用

 首先创建父工程(spring-cloud-alibaba-demo)来管理统一依赖版本,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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
    </parent>
    <groupId>com.yzz</groupId>
    <artifactId>spring-cloud-alibaba-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-cloud-alibaba-demo</name>
    <description>spring-cloud-alibaba-demo</description>
    <properties>
        <java.version>17</java.version>
        <spring-cloud.version>2023.0.0</spring-cloud.version>
        <spring-cloud-alibaba.version>2023.0.0.0-RC1</spring-cloud-alibaba.version>
        <spring-boot.version>3.2.0</spring-boot.version>
        <hutool.version>5.8.18</hutool.version>
        <mybatis-plus.version>3.5.6</mybatis-plus.version>
        <mysql.version>8.0.31</mysql.version>
        <mybatis.version>3.0.4</mybatis.version>
        <fastjson2.version>2.0.53</fastjson2.version>
        <redis.version>1.4.6.RELEASE</redis.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
                <version>${spring-boot.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <version>${spring-boot.version}</version>
            </dependency>
            <!--Spring Cloud Alibaba 的版本信息-->

            <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>
            <!--Spring Cloud 的版本信息-->
            <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>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>${hutool.version}</version>
            </dependency>

            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatis-plus.version}</version>
            </dependency>

            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-spring</artifactId>
                <version>${mybatis.version}</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba.fastjson2</groupId>
                <artifactId>fastjson2</artifactId>
                <version>${fastjson2.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-redis</artifactId>
                <version>${redis.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

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

</project>

 子模块订单服务(service-order)

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yzz</groupId>
        <artifactId>spring-cloud-alibaba-demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>service-order</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>service-order</name>
    <description>service-order</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--Spring Cloud Alibaba Nacos discovery -->
        <dependency>
            <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>
            <exclusions>
                <exclusion>
                    <groupId>com.alibaba.nacos</groupId>
                    <artifactId>nacos-client</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
        </dependency>

        <!--开启Spring Cloud 应用程序启动时加载bootstrap配置文件-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
        <!-- seata -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>com.mybatis</artifactId>
                    <groupId>mybatis-spring</groupId>
                </exclusion>
            </exclusions>
        </dependency>

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

        <dependency>
            <groupId>com.yzz</groupId>
            <artifactId>model</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>service-order</finalName>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

之后就是配置seata了,我们可以通过nacos配置中心来统一管理配置,具体naocs配置中心的使用可以看我前面的一篇文章 nacos的配置中心

service-order服务的bootstrap.yml文件配置如下:

yzz:
  nacos:
    discovery: '@config.nacos.discovery@'
    config: '@config.nacos.config@'
    namespace: '@config.nacos.namespace@'
    username: '@config.nacos.username@'
    password: '@config.nacos.password@'


spring:
  application:
    name: service-order
  cloud:
    nacos:
      config:
        server-addr: ${yzz.nacos.config} #配置中心nacos地址
        username: ${yzz.nacos.username}
        password: ${yzz.nacos.password}
        namespace: ${yzz.nacos.namespace} #命名空间
        group: DEFAULT_GROUP
        file-extension: yaml #配置文件格式
        extension-configs: #扩展配置
          - data-id: seata-config.yml
            refresh: false
          - data-id: redis-config.yml #配置文件dataId
            refresh:  true #是否自动刷新
      discovery:
        server-addr: ${yzz.nacos.discovery}
        namespace: ${yzz.nacos.namespace}
        group: DEFAULT_GROUP
        username: ${yzz.nacos.username}
        password: ${yzz.nacos.password}

 配置中心创建如下文件:service-order,seata-config.yml,redis-config.yml

service-order:

数据库test_1里面就一张订单表(order_table)和一张商品表(produce) 

seata-config.yml:

redis-config.yml:

创建库存服务(service-stock):pom.xml和bootstrap.yml配置与订单服务基本一致,改一下服务端口就可以, 它们共用seata-config.yml,redis-config.yml配置文件,在配置中心添加一个service-stock配置同订单服务一样。注意要改一下bootstrap.yml的spring.application.name

创建一个公共模块来存放服务公共使用的实体:

AddOrderReq:

@Data
public class AddOrderReq implements Serializable {
    /**
     * 主键
     */
    private Integer id;

    /**
     * 订单编号
     */
    private String orderNo;

    /**
     * 用户id
     */
    private Integer userId;

    /**
     * 商品id
     */
    private Integer produceId;

    /**
     * 单价
     */
    private BigDecimal unitPrice;

    /**
     * 数量
     */
    private Integer num;

    /**
     * 总价
     */
    private BigDecimal totalPrice;

    /**
     * 支付状态
     */
    private Integer paymentStatus;


    /**
     * 创建时间
     */

    private LocalDateTime createTime;



    private static final long serialVersionUID = 1L;
}

UpdateStock:

@Data
@AllArgsConstructor
public class UpdateStockReq implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 商品id
     */
    private Integer produceId;
    /**
     * 数量
     */
    private Integer num;
    /**
     * 0-减库存,1-加库存
     */
    private Integer method;
}

订单服务编写创建订单接口(service,mapper层的代码省略)

@RestController
@RequestMapping("/order")
public class OrderController {
   @Autowired
    private OrderService orderService;

   @PostMapping("/create")
    public String createOrder(@RequestBody AddOrderReq req)
   {

       Order order = new Order();
       BeanUtils.copyProperties(req,order);
       String orderNo = UUID.randomUUID().toString();
       order.setOrderNo(orderNo);
       orderService.save( order);
       return orderNo;
   }
}

库存服务扣减库存的接口:

@RestController
@RequestMapping("/stock")
public class StockController {
    @Autowired
    private ProduceService produceService;

    @PostMapping("/updateStock")
    public void updateStock(@RequestBody UpdateStockReq req)
    {
        //判断商品是否存在
        Produce olderProduce = produceService.getById(req.getProduceId());
        if(olderProduce == null) {
            throw new RuntimeException("商品不存在");
        }
        //判断库存是否充足
        if(req.getMethod() == 0 && req.getNum() > olderProduce.getProduceStock()){
            throw new RuntimeException("库存不足");
        }
        //更新库存
        if (req.getMethod() == 0){
            olderProduce.setProduceStock(olderProduce.getProduceStock() - req.getNum());
        }else if (req.getMethod() == 1){
            olderProduce.setProduceStock(olderProduce.getProduceStock() + req.getNum());
        }
        produceService.updateById(olderProduce);

    }
}

创建消费者服务(service-consumer)实现创建订单扣减库存:

 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yzz</groupId>
        <artifactId>spring-cloud-alibaba-demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>service-consumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>service-consumer</name>
    <description>service-consumer</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--Spring Cloud Alibaba Nacos discovery -->
        <dependency>
            <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>
            <exclusions>
                <exclusion>
                    <groupId>com.alibaba.nacos</groupId>
                    <artifactId>nacos-client</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
        </dependency>
        <!--开启Spring Cloud 应用程序启动时加载bootstrap配置文件-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
        </dependency>
        <!-- seata -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
        </dependency>

        <dependency>
            <groupId>com.yzz</groupId>
            <artifactId>model</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>service-consumer</finalName>
        <resources>
<!--            启用占位符-->
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

这里多添加了一个spring-cloud-starter-openfeign依赖用于服务调用

bootstrap.yml配置同前面两个是一样的

nacos配置中心再加一个service-consumer配置:

订单服务和库存服务调用接口:

@FeignClient(name = "service-order")
public interface OrderFeign {
    @PostMapping("/order/create")
    String createOrder(@RequestBody AddOrderReq order);
}
@FeignClient(name = "service-stock")
public interface StockFeign {
    @PostMapping("/stock/updateStock")
    void updateStock(@RequestBody UpdateStockReq req);
}

注意上面所有服务的启动类都要加上这两个注解

@EnableDiscoveryClient //开启服务发现功能
@EnableFeignClients

消费者服务编写购买商品接口:

@RestController
@RequestMapping("/buy")
public class BuyController {
    @Autowired
    private OrderFeign orderFeign;
    @Autowired
    private StockFeign stockFeign;

    @GlobalTransactional(name = "create-order", rollbackFor = Exception.class)
    @RequestMapping("/create")
    public String createOrder(@RequestBody AddOrderReq req) {
        AddOrderReq order = new AddOrderReq();
        order.setProduceId(req.getProduceId());
        order.setNum(req.getNum());
        order.setUserId(1);
        order.setCreateTime(LocalDateTime.now());
        order.setPaymentStatus(0);
        // 调用订单服务
        String orderNo = orderFeign.createOrder(order);
        //调用库存服务
        stockFeign.updateStock(new UpdateStockReq(req.getProduceId(), req.getNum(), 0));
        return orderNo;

    }

测试:

编号为1的商品现在库存是75

订单表:

 

 调用接口购买一件商品:

此时订单表和库存表:

现在我们买100件1号商品,此时创建能成功订单,但扣减库存会失败,我们看一下测试结果:

 

 并没有创建订单和扣减库存,说明执行了事务回滚

我们也可以看一下seata的日志信息:

seata ui界面:

 

总结:

其实只要seata配置好了,只要一个@GlobalTransactional注解就可以了,seata在应用中的使用就是一个@GlobalTransactional注解的使用

核心参数

  • disableGlobalTransaction‌:用于控制全局事务的启用状态,默认为false(开启)。若设置为true,则全局事务功能被禁用。 ‌
  • rollbackFor‌:指定需要回滚的异常类型,支持异常类或异常名称。例如:rollbackFor=RuntimeException.classrollbackForClassName="RuntimeException"。 ‌
  • noRollbackFor‌:指定不需要回滚的异常类型,支持异常类或异常名称。例如:noRollbackFor=Exception.class

注意:事务里面千万不要try...catch捕获异常,就算捕获了也要记得抛出异常,要不然不会回滚 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值