不就是个TCC分布式事务,有那么难吗?

分布式事务——分布式事务简介、分布式事务框架 Seata(AT模式、Tcc模式、Tcc Vs AT)、分布式事务—MQ 最早的分布式事务应用架构很简单,不涉及服务间的访问调用,仅仅是服务内操作涉及到对多个数据库资源的访问。当一个服务操作访问不同的数据库资源,又希望对它们的访问具有事务特性时,就需要采用分布式事务来协调所有的事务参与者。对于上面介绍的分布式事务应用架构,尽管一个服务操作会访问多个数据库资源,但是毕竟整个事务还是控制在单一服务的内部。如果一个服务操作需要调用另外一个服务,这时的事务就需要跨越多个服务了。四种模式,https1.4.01.2.0Seata是什么?一阶段,这些就不再赘述了。总之,... 阅读详情


写在前面
之前网上看到很多写分布式事务的文章,不过大多都是将分布式事务各种技术方案简单介绍一下。很多朋友看了不少文章,还是不知道分布式事务到底怎么回事,在项目里到底如何使用。
所以咱们这篇文章,就用大白话+手工绘图,并结合一个电商系统的案例实践,来给大家讲清楚到底什么是TCC分布式事务。
业务场景介绍
咱们先来看看业务场景,假设你现在有一个电商系统,里面有一个支付订单的场景。
那对一个订单支付之后,我们需要做下面的步骤:

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

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


进一步思考
好,业务场景有了,现在我们要更进一步,实现一个TCC分布式事务的效果。
什么意思呢?也就是说,订单服务-修改订单状态,库存服务-扣减库存,积分服务-增加积分,仓储服务-创建销售出库单。
上述这几个步骤,要么一起成功,要么一起失败,必须是一个整体性的事务。
举个例子,现在订单的状态都修改为“已支付”了,结果库存服务扣减库存失败。那个商品的库存原来是100件,现在卖掉了2件,本来应该是98件了。
结果呢?由于库存服务操作数据库异常,导致库存数量还是100。这不是在坑人么,当然不能允许这种情况发生了!
但是如果你不用TCC分布式事务方案的话,就用个Spring Cloud开发这么一个微服务系统,很有可能会干出这种事儿来。
我们来看看下面的这个图,直观的表达了上述的过程。


所以说,我们有必要使用TCC分布式事务机制来保证各个服务形成一个整体性的事务。
上面那几个步骤,要么全部成功,如果任何一个服务的操作失败了,就全部一起回滚,撤销已经完成的操作。
比如说库存服务要是扣减库存失败了,那么订单服务就得撤销那个修改订单状态的操作,然后得停止执行增加积分和通知出库两个操作。
说了那么多,老规矩,给大家上一张图,大伙儿顺着图来直观的感受一下。


落地实现TCC分布式事务
那么现在到底要如何来实现一个TCC分布式事务,使得各个服务,要么一起成功?要么一起失败呢?
大家稍安勿躁,我们这就来一步一步的分析一下。咱们就以一个Spring Cloud开发系统作为背景来解释。
1、TCC实现阶段一:Try
首先,订单服务那儿,他的代码大致来说应该是这样子的:


如果你之前看过Spring Cloud架构原理那篇文章,同时对Spring Cloud有一定的了解的话,应该是可以理解上面那段代码的。
其实就是订单服务完成本地数据库操作之后,通过Spring Cloud的Feign来调用其他的各个服务罢了。
但是光是凭借这段代码,是不足以实现TCC分布式事务的啊?!兄弟们,别着急,我们对这个订单服务修改点儿代码好不好。
首先,上面那个订单服务先把自己的状态修改为:OrderStatus.UPDATING。
这是啥意思呢?也就是说,在pay()那个方法里,你别直接把订单状态修改为已支付啊!你先把订单状态修改为UPDATING,也就是修改中的意思。
这个状态是个没有任何含义的这么一个状态,代表有人正在修改这个状态罢了。
然后呢,库存服务直接提供的那个reduceStock()接口里,也别直接扣减库存啊,你可以是冻结掉库存。
举个例子,本来你的库存数量是100,你别直接100 - 2 = 98,扣减这个库存!
你可以把可销售的库存:100 - 2 = 98,设置为98没问题,然后在一个单独的冻结库存的字段里,设置一个2。也就是说,有2个库存是给冻结了。
积分服务的addCredit()接口也是同理,别直接给用户增加会员积分。你可以先在积分表里的一个预增加积分字段加入积分。
比如:用户积分原本是1190,现在要增加10个积分,别直接1190 + 10 = 1200个积分啊!
你可以保持积分为1190不变,在一个预增加字段里,比如说prepare_add_credit字段,设置一个10,表示有10个积分准备增加。
仓储服务的saleDelivery()接口也是同理啊,你可以先创建一个销售出库单,但是这个销售出库单的状态是“UNKNOWN”。
也就是说,刚刚创建这个销售出库单,此时还不确定他的状态是什么呢!
上面这套改造接口的过程,其实就是所谓的TCC分布式事务中的第一个T字母代表的阶段,也就是Try阶段。
总结上述过程,如果你要实现一个TCC分布式事务,首先你的业务的主流程以及各个接口提供的业务含义,不是说直接完成那个业务操作,而是完成一个Try的操作。
这个操作,一般都是锁定某个资源,设置一个预备类的状态,冻结部分数据,等等,大概都是这类操作。
咱们来一起看看下面这张图,结合上面的文字,再来捋一捋这整个过程。


2、TCC实现阶段二:Confirm
​然后就分成两种情况了,第一种情况是比较理想的,那就是各个服务执行自己的那个Try操作,都执行成功了,bingo!
这个时候,就需要依靠TCC分布式事务框架来推动后续的执行了。
这里简单提一句,如果你要玩儿TCC分布式事务,必须引入一款TCC分布式事务框架,比如国内开源的ByteTCC、himly、tcc-transaction。
否则的话,感知各个阶段的执行情况以及推进执行下一个阶段的这些事情,不太可能自己手写实现,太复杂了。
如果你在各个服务里引入了一个TCC分布式事务的框架,订单服务里内嵌的那个TCC分布式事务框架可以感知到,各个服务的Try操作都成功了。
此时,TCC分布式事务框架会控制进入TCC下一个阶段,第一个C阶段,也就是Confirm阶段。
为了实现这个阶段,你需要在各个服务里再加入一些代码。
比如说,订单服务里,你可以加入一个Confirm的逻辑,就是正式把订单的状态设置为“已支付”了,大概是类似下面这样子:​


​库存服务也是类似的,你可以有一个InventoryServiceConfirm类,里面提供一个reduceStock()接口的Confirm逻辑,这里就是将之前冻结库存字段的2个库存扣掉变为0。
这样的话,可销售库存之前就已经变为98了,现在冻结的2个库存也没了,那就正式完成了库存的扣减。
积分服务也是类似的,可以在积分服务里提供一个CreditServiceConfirm类,里面有一个addCredit()接口的Confirm逻辑,就是将预增加字段的10个积分扣掉,然后加入实际的会员积分字段中,从1190变为1120。
仓储服务也是类似,可以在仓储服务中提供一个WmsServiceConfirm类,提供一个saleDelivery()接口的Confirm逻辑,将销售出库单的状态正式修改为“已创建”,可以供仓储管理人员查看和使用,而不是停留在之前的中间状态“UNKNOWN”了。
好了,上面各种服务的Confirm的逻辑都实现好了,一旦订单服务里面的TCC分布式事务框架感知到各个服务的Try阶段都成功了以后,就会执行各个服务的Confirm逻辑。
订单服务内的TCC事务框架会负责跟其他各个服务内的TCC事务框架进行通信,依次调用各个服务的Confirm逻辑。然后,正式完成各个服务的所有业务逻辑的执行。
同样,给大家来一张图,顺着图一起来看看整个过程。​


3、TCC实现阶段三:Cancel
​好,这是比较正常的一种情况,那如果是异常的一种情况呢?
举个例子:在Try阶段,比如积分服务吧,他执行出错了,此时会怎么样?
那订单服务内的TCC事务框架是可以感知到的,然后他会决定对整个TCC分布式事务进行回滚。
也就是说,会执行各个服务的第二个C阶段,Cancel阶段。
同样,为了实现这个Cancel阶段,各个服务还得加一些代码。
首先订单服务,他得提供一个OrderServiceCancel的类,在里面有一个pay()接口的Cancel逻辑,就是可以将订单的状态设置为“CANCELED”,也就是这个订单的状态是已取消。
库存服务也是同理,可以提供reduceStock()的Cancel逻辑,就是将冻结库存扣减掉2,加回到可销售库存里去,98 + 2 = 100。
积分服务也需要提供addCredit()接口的Cancel逻辑,将预增加积分字段的10个积分扣减掉。
仓储服务也需要提供一个saleDelivery()接口的Cancel逻辑,将销售出库单的状态修改为“CANCELED”设置为已取消。
然后这个时候,订单服务的TCC分布式事务框架只要感知到了任何一个服务的Try逻辑失败了,就会跟各个服务内的TCC分布式事务框架进行通信,然后调用各个服务的Cancel逻辑。
大家看看下面的图,直观的感受一下。​


总结与思考
​好了,兄弟们,聊到这儿,基本上大家应该都知道TCC分布式事务具体是怎么回事了!
总结一下,你要玩儿TCC分布式事务的话:
首先需要选择某种TCC分布式事务框架,各个服务里就会有这个TCC分布式事务框架在运行。
然后你原本的一个接口,要改造为3个逻辑,Try-Confirm-Cancel。

  • 先是服务调用链路依次执行Try逻辑。
  • 如果都正常的话,TCC分布式事务框架推进执行Confirm逻辑,完成整个事务。
  • 如果某个服务的Try逻辑有问题,TCC分布式事务框架感知到之后就会推进执行各个服务的Cancel逻辑,撤销之前执行的各种操作。

这就是所谓的TCC分布式事务。
TCC分布式事务的核心思想,说白了,就是当遇到下面这些情况时。

  • 某个服务的数据库宕机了。
  • 某个服务自己挂了。
  • 那个服务的redis、elasticsearch、MQ等基础设施故障了。
  • 某些资源不足了,比如说库存不够这些。

先来Try一下,不要把业务逻辑完成,先试试看,看各个服务能不能基本正常运转,能不能先冻结我需要的资源。
如果Try都ok,也就是说,底层的数据库、redis、elasticsearch、MQ都是可以写入数据的,并且你保留好了需要使用的一些资源(比如冻结了一部分库存)。
接着,再执行各个服务的Confirm逻辑,基本上Confirm就可以很大概率保证一个分布式事务的完成了。
那如果Try阶段某个服务就失败了,比如说底层的数据库挂了,或者redis挂了,等等。
此时就自动执行各个服务的Cancel逻辑,把之前的Try逻​辑都回滚,所有服务都不要执行任何设计的业务逻辑。保证大家要么一起成功,要么一起失败。
写到这里,本文差不多该结束了。等一等,你有没有想到一个问题?
如果有一些意外的情况发生了,比如说订单服务突然挂了,然后再次重启,TCC分布式事务框架是如何保证之前没执行完的分布式事务继续执行的呢?
所以,TCC事务框架都是要记录一些分布式事务的活动日志的,可以在磁盘上的日志文件里记录,也可以在数据库里记录。保存下来分布式事务运行的各个阶段和状态。
问题还没完,万一某个服务的Cancel或者Confirm逻辑执行一直失败怎么办呢?
那也很简单,TCC事务框架会通过活动日志记录各个服务的状态。
举个例子,比如发现某个服务的Cancel或者Confirm一直没成功,会不停的重试调用他的Cancel或者Confirm逻辑,务必要他成功!
当然了,如果你的代码没有写什么bug,有充足的测试,而且Try阶段都基本尝试了一下,那么其实一般Confirm、Cancel都是可以成功的!
最后,再给大家来一张图,来看看给我们的业务,加上分布式事务之后的整个执行流程:​


​不少大公司里,其实都是自己研发TCC分布式事务框架的,专门在公司内部使用,比如我们就是这样。
不过如果自己公司没有研发TCC分布式事务框架的话,那一般就会选用开源的框架。
这里笔者给大家推荐几个比较不错的框架,都是咱们国内自己开源出去的:ByteTCC,tcc-transaction,himly。
只要把那些框架整合到你的系统里,很容易就可以实现上面那种奇妙的TCC分布式事务的效果了。​

分布式事务Seata源码解析13:TCC事务模式实现原理 1、TCC事务模式实现原理; 2、TCC资源TCCResource解析; 3、TCCResource注册到TC的流程; 4、TCC执行上下文BusinessActionContext详解; 5、TCC分支事务执行流程、ActionInterceptorHandler解析; 6、@LocalTCC使用原理、@TwoPhaseBusinessAction使用原理、@BusinessActionContextParameter使用原理; 7、TCC分支事务提交、回滚原理。 阅读详情

相关推荐

【CV论文精读】【协同感知综述】Collaborative Perception for Autonomous Driving :Current Status and Future Trend

感知是自动驾驶系统的关键模块之一,近年来取得了很大进展。然而,单个车辆的有限能力导致感知性能提高的瓶颈。为了突破个体感知的局限,协作感知被提出,它使车辆能够共享信息来感知视线和视野之外的环境。本文综述了有前途的协作感知技术的相关工作,包括介绍了基本概念,概括了协作模式,总结了协作感知的关键要素和应用。最后,我们讨论了这一研究领域面临的挑战和问题,并给出了一些潜在的进一步方向。

weixin_44184852的博客 4690

分布式事务之TCC服务设计和实现注意事项

1、TCC简介 TCC是一种比较成熟的分布式事务解决方案,可用于解决跨库操作的数据一致性问题; TCC是服务化的两阶段编程模型,其Try、Confirm、Cancel 3个方法均由业务编码实现; 其中Try操作作为一阶段,负责资源的检查和预留,Confirm操作作为二阶段提交操作,执行真正的业务,Cancel是预留资源的取消; 如下图所示,业务实现TCC...

weixin_34307464的博客 1328

Android Profiler 帧率优化实战与性能调优

本文详细介绍了使用Android Profiler进行帧率优化与性能调优的实战方法。通过分析主线程状态、FPS曲线和渲染阶段耗时,精准定位卡顿根源,并提供减少过度绘制、优化绘制命令及改善资源使用的具体策略。文章结合电商、游戏等真实案例,帮助开发者有效解决卡顿问题,提升应用流畅度。

palm99的专栏 536

分布式事务(三)———TCC 解决方案

分布式事务解决方案之TCC解决方案 以及 seata的实现

共勉 5304

DSP(数字信号处理器)技术概要

数字信号处理器(digital signal processor,DSP)是一种用于数字信号处理的可编程微处理器,它的诞生与快速发展,使各种数字信号处理算送得以实时实现,为数字信号处理的研究和应用打开了新局面,提供了低成本的实际工作环境和应用平台,推动了新的理论和应用领域的发展。目前,DSP技术在通信、航空、航天。雷达、工业控制、医疗、网络及家用电器等各个领域都得到了广泛应用。 1.1 DSP系统和芯片的结构特点1.1.1 DSP系统的基本结构通过传感数将非电物理量转换为模拟电信号,预处理一般包括放大器和滤

m0_46582485的博客 2万+

(SCADA)监控与数据采集系统

SCADA应用于监控和采集数据来控制工业过程软件。它通过收集和传输实时数据,帮助操作员监视和控制各种设备和过程。

软件技术的专栏 4544

TCC详解及存在哪些问题

是除可靠消息队列以外的另一种常见的分布式事务机制,它是由数据库专家帕特 · 赫兰德()在2007年撰写的论文《Life beyond Distributed Transactions: An Apostate’s Opinion》中提出的。正式以作为名称的是Atomikos公司,其注册了TCC商标。上次我们分享的使用RocketMQ实现分布式事务,虽然它也能保证最终的结果是相对可靠的,过程也足够简单(相对于TCC来说),但可靠消息队列的整个实现过程完全没有任何隔离性可言。

2301_76166241的博客 4047

告别JTAG!用Artix-7和SPI Flash实现FPGA远程升级的保姆级教程

本文详细介绍了如何利用Artix-7 FPGA和SPI Flash实现FPGA远程升级(OTA)的完整方案。通过硬件连接、Vivado工程配置和STM32模拟更新等步骤,帮助开发者告别传统的JTAG烧录方式,实现高效、安全的远程固件更新,特别适用于嵌入式系统开发中的现场维护场景。

weixin_33964987的博客 364

分布式事务解决方案之TCC

分布式事务解决方案之TCC

大道至简,持之以恒! 3694

Ollama运行DeepSeek大模型调优指南:GPU与CPU协同实现性能最大化

Ollama运行DeepSeek大模型调优指南

qq_32358423的博客 3997

PyTorch深度学习实战(3)——使用PyTorch构建神经网络

PyTorch 是一个用于构建深度神经网络的库,具有灵活性和可扩展性,可以轻松自定义模型。在本节中,我们将使用 PyTorch 库构建神经网络,利用张量对象操作和梯度值计算更新网络权重,并利用 Sequential 类简化网络构建过程,最后还介绍了如何使用 save、load 方法保存和加载模型,以节省模型训练时间。

盼小辉丶的博客 8万+

什么是分布式事务

什么是分布式事务

qq_30939943的博客 1196

华为OD机试 - 取出尽量少的球 - 感谢@吴修柯反馈(Python/JS/C/C++ 双机位A卷 200分)

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。感谢@吴修柯反馈,2025-03-22,A卷200分考试真题。某部门开展 Family Day 开放日活动,其中有个从桶里取球的游戏。有 N 个容量一样的小桶等距排开,且每个小桶都默认装了数量不等的小球,每个小桶装的小球数量记录在数组 bucke

学Java,找哪吒 1485

如何利用事务消息实现分布式事务?

那什么是事务呢?如果我们需要对若干数据进行更新操作,为了保证这些数据的完整性和一致性,我们希望这些更新操作**要么都成功,要么都失败。**至于更新的数据,不只局限于数据库中的数据,可以是磁盘上的一个文件,也可以是远端的一个服务,或者以其他形式存储的数据。这就是通常我们理解的事务。其实这段对事务的描述不是太准确也不完整,但是,它更易于理解,大体上也是正确的。所以我还是倾向于这样来讲“事务”这个比较抽象的概念。一个严格意义的事务实现,应该具有4个属性:原子性、一致性、隔离性、持久性。

qq_33240556的博客 800

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Java并发编程--39-什么是分布式事务?与本地事务有何区别?

分布式事务与本地事务的核心区别 本地事务在单个数据库内通过ACID特性保证数据一致性,而分布式事务面临跨服务、跨数据库的挑战。主要区别包括: 范围差异:本地事务限于单一数据库,分布式事务涉及多个独立节点 一致性模型:本地事务是强一致性,分布式事务通常采用最终一致性 故障处理:本地事务回滚简单,分布式事务需处理部分成功场景 实现复杂度:分布式事务需额外协调机制,复杂度显著提高 典型解决方案包括2PC、TCC、Saga等,需要根据业务场景选择合适方案。

weisian的博客 3603

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

讲解分布式事务的一篇良心之作

目录: 1.什么是事务? 2.换个角度看事务 3.Java中的事务 4.啥又是分布式事务? 5.分布式事务的几种实现思路 6.总结 写在前面 在分布式、微服务大行其道的今天,相信大家对这些名词都不会陌生。而说到使用分布式,或者拆分微服务的好处,你肯定能想到一大堆。 比如每个人只需要维护自己单独的服务,没有了以前的各种代码冲突。自己想测试、想发布、想升级,只需要care自己写...

疯一样的女子 202

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

基于TCC的分布式事务

分布式的架构中,分布式的事务是一个绕不过的挑战,微服务理念的流行让分布式的问题日益突出。在公司内部, 笔者所接触的管理系统中实际上也存在着分布式事务。这里假设有这三个系统(cim、xfunds、cert)存在客户的同步问题。//cim 系统签约用户(cim本地事务)//新增成功//新增失败,导致和cert系统数据不一致try {//祈祷cert这个接口调用成功。

程序猿进阶 1760

分布式事务TCC

之前网上看到很多写分布式事务的文章,不过大多都是将分布式事务各种技术方案简单介绍一下。很多朋友看了还是不知道分布式事务到底怎么回事,在项目里到底如何使用。 所以这篇文章,就用大白话+手工绘图,并结合一个电商系统的案例实践,来给大家讲清楚到底什么是 TCC 分布式事务。 ###一、业务场景介绍 咱们先来看看业务场景,假设你现在有一个电商系统,里面有一个支付订单的场景。 那对一个订单支付之后,我们需要做下面的步骤: 更改订单的状态为“已支付” 扣减商品库存 给会员增加积分 创建销售出库单通知仓库发货 这是一

少年闰土的博客 3877

分布式事务 Seata TCC 模式深度解析

2019 年 3 月,蚂蚁金服加入分布式事务 Seata 的社区共建中,并贡献其 TCC 模式。本期是 SOFAChannel 第四期,主题:分布式事务 Seata TCC 模式深度解析,本文根据觉生的直播整理。 大家晚上好,我是 Seata Committer 觉生,来自蚂蚁金服数据中间件团队。今天的内容主要分为以下四个部分: Seata TCC 模式的原理解析; 从 TCC 的业务模型与...

怀素的专栏 2万+

分布式事务你们如何解决的?为什么当时不考虑TCC呢?TCC有什么缺点?

参与者没执行Try(或结果未上报),却收到了Cancel指令。

weixin_44984196的博客 1470

分布式事务之TCC

来源:云栖社区 |作者:绍辉 | 原文地址见文末 一、TCC简介 TCC是一种比较成熟的分布式事务解决方案,可用于解决跨库操作的数据一致性问题; TCC是服务化的两阶段编程模型,其Try、Confirm、Cancel 3个方法均由业务编码实现; 其中Try操作作为一阶段,负责资源的检查和预留,Confirm操作作为二阶段提交操作,执行真正的业务,Cancel是预留资源的取消; ...

hellozhxy的博客 1万+

[分布式事务-TCC] 2. TCC的异常场景及应对机制

文章导航TCC的异常场景幂等处理产生原因应对策略空回滚产生原因应对策略资源悬挂产生原因应对策略三种异常总结幂等空回滚资源悬挂共通点 TCC的异常场景 在分布式系统中,随时随地都需要面对网络超时,网络重发和服务器宕机等问题。所以分布式事务框架作为搭载在分布式系统之上的一个框架型应用也绕不开这些问题。具体而言,有以下常见问题: 幂等处理 空回滚 资源悬挂 这些异常的应对需要TCC框架的支持和解决方...

不忘初心,好好沉淀 1万+
上一篇: MySQL 啥时候用表锁,啥时候用行锁?
下一篇: 聊聊Java中代码优化的30个小技巧
程序员职业指南
博客等级 码龄4年 2136粉丝 960原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值