TCC事务原理

317 阅读7分钟

TCC(Try-Confirm-Cancel)是分布式事务领域中一种基于业务补偿的解决方案,核心思想是通过在业务层面拆分事务为三个阶段,实现分布式场景下的最终一致性。它不依赖数据库的事务协议,而是通过业务逻辑的定制化设计,解决跨服务调用时的数据一致性问题。

1 TCC 的核心思想

TCC 是一种 “补偿型” 分布式事务机制,其核心是将一个完整的分布式事务拆分为三个业务逻辑阶段,通过业务代码的定制化实现,保证跨服务操作的最终一致性。
与传统的 2PC(两阶段提交)等协议层方案不同,TCC 完全由业务代码控制,更灵活且性能更高,但对业务侵入性强。

2 TCC 的三个阶段

TCC 将分布式事务的执行过程拆分为Try(尝试)、Confirm(确认)、Cancel(取消)  三个阶段,每个阶段对应业务层面的具体逻辑:

2.1 Try(尝试阶段)

核心目标:检查资源可用性,并预留业务所需的资源(非实际执行)。

  • 作用:为后续的确认或取消操作做准备,确保业务操作具备执行条件(如资源充足、权限合法等)。
  • 举例:电商下单场景中,Try 阶段需完成:
    • 订单服务:创建 “待支付” 状态的订单(未确认);
    • 库存服务:检查商品库存是否充足,并锁定对应数量的库存(不实际扣减);
    • 支付服务:检查用户账户余额是否充足,并预留支付金额(不实际扣款)。

2.2 Confirm(确认阶段)

核心目标:在 Try 阶段成功后,实际执行业务操作(基于 Try 阶段预留的资源)。

  • 作用:确认事务最终执行,释放 Try 阶段预留的资源(转为实际消耗)。
  • 触发条件:只有当所有参与方的 Try 阶段都成功时,才会执行 Confirm。
  • 举例:电商下单中,Confirm 阶段需完成:
    • 订单服务:将 “待支付” 订单更新为 “已支付”;
    • 库存服务:将 Try 阶段锁定的库存实际扣减;
    • 支付服务:将 Try 阶段预留的金额从用户账户中实际扣除。

2.3 Cancel(取消阶段)

核心目标:在 Try 阶段失败时,回滚 Try 阶段预留的资源(补偿操作)。

  • 作用:消除 Try 阶段的影响,保证数据一致性。
  • 触发条件:只要有一个参与方的 Try 阶段失败,就需要对所有参与方执行 Cancel。
  • 举例:电商下单中,若库存服务 Try 失败(库存不足),Cancel 阶段需完成:
    • 订单服务:将 “待支付” 订单改为 “已取消”;
    • 库存服务:释放 Try 阶段锁定的库存(若已锁定);
    • 支付服务:释放 Try 阶段预留的金额(若已预留)。

3 TCC 的关键技术点

在设计TCC分布式事务框架时必须要考虑出现的异常情况,在执行TCC分布式事务时候,需要记录一些分布式事务的活动日志,将这些活动日志存储到文件或者数据库中,将分布式事务的各个阶段和每个阶段执行的状态全部记录下来。 TCC 的核心是业务逻辑的定制化,因此需要解决以下技术问题:

3.1 幂等性设计

  • 问题:Confirm/Cancel 可能因网络重试、协调者故障等原因被重复调用,导致数据错误(如重复扣减库存)。
  • 解决:通过唯一标识(如事务 ID)记录操作状态,确保重复调用时结果一致。例如:
    • 库存扣减时,检查 “事务 ID 是否已执行”,若已执行则直接返回成功。

3.2 空回滚(Null Rollback)

  • 问题:若参与方未收到 Try 请求(如网络故障),但协调者因超时触发 Cancel,此时该参与方无资源可回滚。
  • 解决:允许 “空回滚”(即无操作时返回成功),避免因某一方无法回滚导致整个事务阻塞。

3.3 悬挂(Hanging)

  • 问题:Cancel 执行后,Try 请求才到达参与方,导致资源被错误预留(此时 Cancel 已执行,无法再回滚)。
  • 解决:记录事务状态,若已执行过 Cancel,则拒绝后续的 Try 请求。

3.4 重试机制

  • 问题:Confirm/Cancel 可能因网络波动、服务临时故障失败。
  • 解决:协调者需实现重试机制(如定时任务),直到所有参与方的 Confirm/Cancel 执行成功。

4 TCC 的关键技术

下面我们以Hmily为例,简单介绍下实现TCC分布式事务框架的关键技术

4.1 AOP切面

实现TCC分布式事务的第一个核心技术就是AOP切面。无论是TCC分布式事务的发起者,还是参与者,都需要经过AOP切面的处理。通过AOP切面拦截具体的业务逻辑,在AOP切面中执行事务日志的记录、远程调用等逻辑。

4.2 反射技术

TCC分布式事务中Confirm阶段的方法和Cancel阶段的方法是通过反射技术调用的。这也就是Hmily框架在Try阶段的方法上使用注解来指定Confirm方法和Cancel方法的原因。在Try阶段的方法上使用注解指定Confirm方法和Cancel方法,Hmily框架会在执行完Try方法后,使用反射技术自动调用Confirm方法或者Cancel方法

4.3 持久化技术

在分布式事务的实现中,所有参与事务的服务都存在数据的持久化操作。在分布式环境中,由于网络的不稳定性,随时都有可能出现调用服务方法失败的情况,在TCC分布式事务中,需要保证数据的最终一致性。如果只有一部分服务的请求被正常处理,则另一部分服务的请求最终也需要被处理,对请求数据持久化必不可少。Hmily框架不仅支持使用Redis、ZooKeeper、文件、缓存、ETCD、MongoDB等进行持久化操作,还提供了SPI扩展接口,使得具体业务可以根据自己的需要实现自己的持久化技术

4.4 序列化技术

在分布式环境中,数据的持久化和在网络中的传输,都需要序列化技术的支持。Hmily支持的序列化技术有JDK自带的序列化技术、Hessian序列化技术、Kyro序列化技术等。

4.5 定时任务

在分布式环境中,由于网络的不稳定性,难免会出现方法调用失败的情况,此时,需要利用定时任务来重试方法的调用操作。Hmily框架实现了当方法调用失败时,使用定时任务进行重试的机制。

4.6 动态代理

分布式环境中存在很多远程调用框架,在分布式事务的实现过程中,需要通过动态代理的方式支持多种远程调用框架。例如,在Hmily中通过动态代理支持多种远程调用框架,这些远程框架包括Dubbo、gRPC、Spring Cloud等

4.7 多配置源技术

在分布式环境中,为了便于管理各业务系统的配置,往往会集中存储各业务系统的配置,并通过相应的技术快速同步到各个业务系统的本地缓存中。由于在真正的业务场景中,会存在不同的配置存储技术,因此实现分布式事务的时候,需要支持多配置源技术,例如:在Hmily矿建中,就实现了多种配置源技术,这些配置源包括Apollo、ETCD、Nacos、Zookeeper、本地存储等

5 TCC 的优势与局限性

维度优势局限性
性能无数据库锁表操作,依赖业务逻辑,性能较高
灵活性完全由业务代码控制,可根据场景定制(如预留资源的粒度)
侵入性无(优势是相对协议层方案)强侵入性:需业务代码实现 Try/Confirm/Cancel 三个接口
开发成本高:需处理幂等性、空回滚、悬挂等异