前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >分布式事务(SeataClient)

分布式事务(SeataClient)

作者头像
问天丶天问
发布2024-03-07 09:05:28
790
发布2024-03-07 09:05:28
举报
文章被收录于专栏:问天丶天问问天丶天问

问题场景

元数据

  • 库存 100
  • 订单记录为空

下单操作

代码语言:javascript
复制
    @Autowired
    RestTemplate restTemplate;

    /**
     * 下单
     *
     * @return
     */
    @Transactional  // 开启事务 异常后触发数据库回滚操作
    @Override
    public Order create(Order order) {
        // 插入订单
        orderMapper.insert(order);

        // 扣减库存 
        MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();paramMap.add("productId", order.getProductId());
        String msg = restTemplate.postForObject("http://localhost:8071/stock/reduct", paramMap, String.class);

        // 制造异常
        int a = 1 / 0;

        return order;
    }

问题解决

  • 上述问题是 A服务 调用 B服务,因此A服务的事务无法回滚B服务的操作
  • 微服务架构下,类似场景频繁遇到,因此就需要引入分布式事务组件 Seata

SeataServer

    >> SeataServer的搭建,上一篇已详述,这里就不多介绍了。

引入依赖

代码语言:text
复制
<!--nacos-服务注册发现-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
 
<!--1. 添加openfeign依赖 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
 
<!--seata的依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

增加配置

  • 订单、库存服务均增加 seata 、nacos 配置
代码语言:text
复制
spring:
  datasource:
    username: root
    password: xxxxx
    url: jdbc:mysql://localhost:3307/seata_stock?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
 
    #初始化时运行sql脚本
    schema: classpath:sql/schema.sql
    initialization-mode: never
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8847
        username: nacos
        password: nacos
    alibaba:
      seata:
        tx-service-group: my_test_tx_group
  application:
    name: stock-seata
 
seata:
  registry:
    # 配置seata的注册中心, 告诉seata client 怎么去访问seata server(TC)    type: nacos
    nacos:
      server-addr: 127.0.0.1:8847  # seata server 所在的nacos服务地址      
      application: seata-server    # seata server 的服务名seata-server ,如果没有修改可以不配      
      username: nacos
      password: nacos
      group: SEATA_GROUP          # seata server 所在的组,默认就是SEATA_GROUP,没有改也可以不配  
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8847
      username: nacos
      password: nacos
      group: SEATA_GROUP

编写OpenFeign接口

 >> 启动类增加 @EnableFeignClients 注解

代码语言:text
复制
@FeignClient(value = "stock-seata", path = "/stock")
public interface StockFeignService {
 
//    @RequestMapping("/reduct")
//    public String reduct(@RequestParam(value="productId") Integer productId){
//        stockService.reduct(productId);
//        return "扣减库存";
//    }
 
    @RequestMapping("/reduct")
    String reduct(@RequestParam(value = "productId") Integer productId);
}

修改调用类

>> @Transactional 变更为 @GlobalTransactional

代码语言:text
复制
    @Autowired
    StockFeignService stockFeignService;
 
    /**
     * 下单
     * @return
     */
//    @Transactional
//    @Override
//    public Order create(Order order) {
//        // 插入订单
//        orderMapper.insert(order);
//
//
//        // 扣减库存
//        MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
//        paramMap.add("productId", order.getProductId());
//
//        String msg = restTemplate.postForObject("http://localhost:8071/stock/reduct", paramMap,String.class );
//
//        // 制造异常
//        int a=1/0;
//
//        return order;
//    }
 
    /**
     * 下单
     * @return
     */
    @GlobalTransactional
    @Override
    public Order create(Order order) {
        // 插入订单
        orderMapper.insert(order);
 
 
        // 扣减库存
        stockFeignService.reduct(order.getProductId());
 
        // 制造异常
        int a=1/0;
 
        return order;
    }

启动服务运行测试

>> 库存表数量为 99 ,订单表记录为空

  • 订单失败场景
代码语言:text
复制
    @GlobalTransactional
    @Override
    public Order create(Order order) {
        // 插入订单
        orderMapper.insert(order);
 
 
        // 扣减库存
        stockFeignService.reduct(order.getProductId());
 
        // 制造异常
//        int a=1/0;
 
        return order;
    }
  • 下单成功, 库存 - 1 

总结 

       微服务框架下,分布式事务的控制已多见不怪了,Seata组件就是其中的一种解决方案;本文介绍了Seata客户端使用,希望对你有所帮助!!!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-03-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题场景
    • 元数据
      • 下单操作
      • 问题解决
        • SeataServer
          • 引入依赖
            • 增加配置
              • 编写OpenFeign接口
                • 修改调用类
                  • 启动服务运行测试
                  • 总结 
                  相关产品与服务
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档