• 【SpringCloudAlibaba】Seata分布式事务使用


    分布式事务问题示例

    单体应用被拆分成微服务应用,原来的三个模块被拆分成三个独立的应用,分别使用三个独立的数据源,
    业务操作需要调用三个服务来完成。此时每个服务内部的数据一致性由本地事务来保证,但是全局的数据一致性问题没法保证。
    在这里插入图片描述

    Seata概述、官网

    官网
    http://seata.io/zh-cn/
    下载
    https://github.com/seata/seata/releases

    一个典型的分布式事务过程

    分布式事务处理过程的一ID+三组件模型

    • Transaction ID XID:全局唯一的事务ID;
    • Transaction Coordinator (TC):事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚;
    • Transaction Manager ™:控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议;
    • Resource Manager (RM):控制分支事务,负责分支注册、状态汇报,并接收事务协调器的指令,驱动分支(本地)事务的提交和回滚;

    处理过程

    1. TM 向 TC 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的 XID;
    2. XID 在微服务调用链路的上下文中传播;
    3. RM 向 TC 注册分支事务,将其纳入 XID 对应全局事务的管辖;
    4. TM 向 TC 发起针对 XID 的全局提交或回滚决议;
    5. TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求。
      在这里插入图片描述

    全局@GlobalTransactional

    相较于Spring的注解@Transactional

    分布式交易解决方案流程图

    在这里插入图片描述

    Seata安装

    下载

    版本1.7
    https://github.com/seata/seata/releases

    修改conf目录下的application.yml配置文件

    1. 先备份原始application.yml文件
    2. 主要修改:自定义事务组名称+事务日志存储模式为db+数据库连接信息(示例参考application.example.yml)
    3. 建表sql在script/server/db

    dashboard

    http://localhost:7091/
    默认7091端口
    切换中文
    在这里插入图片描述

    demo

    @GlobalTransactional(name = “fsp-create-order”,rollbackFor = Exception.class)
    name自己取,唯一就可,rollbackFor异常抛出,

    • 未加该注释出现的问题:示例中 accountService.decrease(order.getUserId(),order.getMoney());调用不成功但是会继续修改订单状态并且会减少账户中值
    //Service全都使用Feign可设置Time.Sleep来模拟Feign调用不成功
    //示例中
    //@GlobalTransactional(name = "fsp-create-order",rollbackFor = Exception.class)
    public void create(Order order)
    {
        log.info("----->开始新建订单");
        //1 新建订单
        orderDao.create(order);
    
        //2 扣减库存
        log.info("----->订单微服务开始调用库存,做扣减Count");
        storageService.decrease(order.getProductId(),order.getCount());
        log.info("----->订单微服务开始调用库存,做扣减end");
    
        //3 扣减账户
        log.info("----->订单微服务开始调用账户,做扣减Money");
        accountService.decrease(order.getUserId(),order.getMoney());
        log.info("----->订单微服务开始调用账户,做扣减end");
    
        //4 修改订单状态,从零到1,1代表已经完成
        log.info("----->修改订单状态开始");
        orderDao.update(order.getUserId(),0);
        log.info("----->修改订单状态结束");
    
        log.info("----->下订单结束了,O(∩_∩)O哈哈~");
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    //模拟Feign调用不成功示例,Feign默认超时1秒不成功
    public void decrease(Long userId, BigDecimal money) {
        LOGGER.info("------->account-service中扣减账户余额开始");
        //模拟超时异常,全局事务回滚
        //暂停几秒钟线程
        try { TimeUnit.SECONDS.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); }
        accountDao.decrease(userId,money);
        LOGGER.info("------->account-service中扣减账户余额结束");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    电力安全智慧云平台:引领更安全的用电新时
    WordPress主题开发(六)之—— 模版文件和自定义模板进阶
    分享积分兑换小程序开发制作功能介绍
    MySQL常见的数据查询慢甚至导致死锁问题
    简单剖析程序的翻译过程!
    E-梅莉的市场经济学
    AQUATOX水环境与水生态模型教程
    编码踩坑——多线程可能带来意想不到的OOM
    python NumPy入门篇
    告别传统FTP!该了解一下替代FTP的新产品了
  • 原文地址:https://blog.csdn.net/qq_45742250/article/details/132542082