TCC分布式事务详解

本文详细介绍了TCC(Try-Confirm-Cancel)分布式事务的原理与实现,包括Try阶段的资源预留,Confirm阶段的业务确认,以及Cancel阶段的回滚操作。在Try阶段,各服务进行预备操作,如冻结库存、预增加积分等;Confirm阶段正式执行业务逻辑;Cancel阶段在服务异常时执行,撤销Try阶段的操作。文章还探讨了可靠消息最终一致性方案,通过消息服务确保消息的100%可靠投递和接收,以及在RocketMQ等MQ中间件中的应用。最后,文章讨论了高可用保障实践,包括MQ故障时的降级策略,利用KV存储实现的队列和故障自动恢复机制。
摘要由CSDN通过智能技术生成

1|0业务场景介绍

 

咱们先来看看业务场景,假设你现在有一个电商系统,里面有一个支付订单的场景。

那对一个订单支付之后,我们需要做下面的步骤:

  • 更改订单的状态为“已支付”
  • 扣减商品库存
  • 给会员增加积分
  • 创建销售出库单通知仓库发货

这是一系列比较真实的步骤,无论大家有没有做过电商系统,应该都能理解。

2|0进一步思考

 

好,业务场景有了,现在我们要更进一步,实现一个 TCC 分布式事务的效果。

什么意思呢?也就是说,[1] 订单服务-修改订单状态,[2] 库存服务-扣减库存,[3] 积分服务-增加积分,[4] 仓储服务-创建销售出库单。

上述这几个步骤,要么一起成功,要么一起失败,必须是一个整体性的事务。

举个例子,现在订单的状态都修改为“已支付”了,结果库存服务扣减库存失败。那个商品的库存原来是 100 件,现在卖掉了 2 件,本来应该是 98 件了。

结果呢?由于库存服务操作数据库异常,导致库存数量还是 100。这不是在坑人么,当然不能允许这种情况发生了!

但是如果你不用 TCC 分布式事务方案的话,就用个 Spring Cloud 开发这么一个微服务系统,很有可能会干出这种事儿来。

我们来看看下面的这个图,直观的表达了上述的过程:

所以说,我们有必要使用 TCC 分布式事务机制来保证各个服务形成一个整体性的事务。

上面那几个步骤,要么全部成功,如果任何一个服务的操作失败了,就全部一起回滚,撤销已经完成的操作。

比如说库存服务要是扣减库存失败了,那么订单服务就得撤销那个修改订单状态的操作,然后得停止执行增加积分和通知出库两个操作。

说了那么多,老规矩,给大家上一张图,大伙儿顺着图来直观的感受一下:

3|0落地实现 TCC 分布式事务

 

那么现在到底要如何来实现一个 TCC 分布式事务,使得各个服务,要么一起成功?要么一起失败呢?

大家稍安勿躁,我们这就来一步一步的分析一下。咱们就以一个 Spring Cloud 开发系统作为背景来解释。

3|1TCC 实现阶段一:Try

 

首先,订单服务那儿,它的代码大致来说应该是这样子的:

<span style="color:#222222"><code><span style="color:#cb7832 !important">public</span> <span style="color:#cb7832 !important">class</span> <span style="color:#e0c46c !important">OrderService</span> {

    <span style="color:#7f7f7f !important">// 库存服务</span>
    <span style="color:#959f60 !important">@Autowired</span>
    <span style="color:#cb7832 !important">private</span> InventoryService inventoryService;

    <span style="color:#7f7f7f !important">// 积分服务</span>
    <span style="color:#959f60 !important">@Autowired</span>
    <span style="color:#cb7832 !important">private</span> CreditService creditService;

    <span style="color:#7f7f7f !important">// 仓储服务</span>
    <span style="color:#959f60 !important">@Autowired</span>
    <span style="color:#cb7832 !important">private</span> WmsService wmsService;

    <span style="color:#7f7f7f !important">// 对这个订单完成支付</span>
    <span style="color:#cb7832 !important">public</span> <span style="color:#cb7832 !important">void</span> <span style="color:#e0c46c !important">pay</span><span style="color:#b9b9b9 !important">()</span>{
        <span style="color:#7f7f7f !important">//对本地的的订单数据库修改订单状态为"已支付"</span>
        orderDAO.updateStatus(OrderStatus.PAYED);

        <span style="color:#7f7f7f !important">//调用库存服务扣减库存</span>
        inventoryService.reduceStock();

        <span style="color:#7f7f7f !important">//调用积分服务增加积分</span>
        creditService.addCredit();

        <span style="color:#7f7f7f !important">//调用仓储服务通知发货</span>
        wmsService.saleDelivery();
    }
}</code></span>

如果你之前看过 Spring Cloud 架构原理那篇文章,同时对 Spring Cloud 有一定的了解的话,应该是可以理解上面那段代码的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值