2023-08-12  阅读(6)
原文作者:Ressmix 原文地址:https://www.tpvlog.com/article/67

一、简介

2007年,Pat Helland发表了一篇名为《Life beyond Distributed Transactions: an Apostate’s Opinion》的论文,提出了 TCC(Try-Confirm-Cancel) 的概念。

两阶段提交(2PC)三阶段提交(3PC)并不适用于并发量大的业务场景。TCC事务机制相比于2PC、3PC,不会锁定整个资源,而是通过引入 补偿机制 ,将资源转换为业务逻辑形式,锁的粒度变小。

TCC的核心思想是: 针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作 ,分为三个阶段:

  • Try: 这个阶段对各个服务的资源做检测以及对资源进行锁定或者预留;
  • Confirm : 执行真正的业务操作,不作任何业务检查,只使用Try阶段预留的业务资源,Confirm操作要求具备幂等设计,Confirm失败后需要进行重试;
  • Cancel: 如果任何一个服务的业务方法执行出错,那么这里就需要进行补偿,即执行回滚操作,释放Try阶段预留的业务资源 ,Cancel操作要求具备幂等设计,Cancel失败后需要进行重试。

202308122214473001.png

举个例子,电商系统中有两个服务:订单服务A、库存服务B:
对外提供服务时,必须接受一些不确定性,即对服务A/B的一次调用仅是一个临时性操作,服务消费方保留了后续的取消权。
如果消费方认为全局事务应该rollback,它会要求取消之前的临时性操作;如果消费方认为全局事务应该commit时,它会进行的一个确认操作。

二、TCC的执行

TCC将一次事务操作分为三个阶段:Try、Confirm、Cancel,我们通过一个订单/库存的示例来理解。假设我们的分布式系统一共包含4个服务:订单服务、库存服务、积分服务、仓储服务,每个服务有自己的数据库,如下图:

202308122214479322.png

2.1 Try

Try阶段一般用于锁定某个资源,设置一个预备状态或冻结部分数据。对于示例中的每一个服务,Try阶段所做的工作如下:

  • 订单服务:先置一个中间状态“UPDATING”,而不是直接设置“支付成功”状态;
  • 库存服务:先用一个冻结库存字段保存冻结库存数,而不是直接扣掉库存;
  • 积分服务:预增加会员积分;
  • 仓储服务:创建销售出库单,但状态是UNKONWN。

202308122214485123.png

2.2 Confirm

根据Try阶段的执行情况,Confirm分为两种情况:

  1. 理想情况下,所有Try全部执行成功,则执行各个服务的Confirm逻辑;
  2. 部分服务Try执行失败,则执行第三阶段——Cancel。

Confirm阶段一般需要各个服务自己实现Confirm逻辑:

  • 订单服务:confirm逻辑可以是将订单的中间状态变更为PAYED-支付成功;
  • 库存服务:将冻结库存数清零,同时扣减掉真正的库存;
  • 积分服务:将预增加积分清零,同时增加真实会员积分;
  • 仓储服务:修改销售出库单的状态为已创建-CREATED。

202308122214499904.png

Confirm阶段的各个服务本身可能出现问题,这时候一般就需要TCC框架了(比如ByteTCC,tcc-transaction,himly),TCC事务框架一般会记录一些分布式事务的活动日志,保存事务运行的各个阶段和状态,从而保证整个分布式事务的最终一致性。

2.3 Cancel

如果Try阶段执行异常,就会执行Cancel阶段。比如:对于订单服务,可以实现的一种Cancel逻辑就是:将订单的状态设置为“CANCELED”;对于库存服务,Cancel逻辑就是:将冻结库存扣减掉,加回到可销售库存里去。

202308122214509485.png

许多公司为了简化TCC的使用,通常会将一个服务的某个核心接口拆成两个,比如库存服务的扣减库存接口,拆成两个子接口:①扣减接口 ②回滚扣减库存接口,由TCC框架来保证当某个接口执行失败后去执行对应的rollback接口。

三、总结

从正常的流程上讲,TCC仍然是一个两阶段提交协议。但是,在执行出现问题的时候,有一定的自我修复能力,如果任何一个事务参与者出现了问题,协调者可以通过执行逆操作来取消之前的操作,达到最终的一致状态(比如冲正交易、查询交易)。

从TCC的执行流程也可以看出,服务提供方需要提供额外的 补偿逻辑 ,那么原来一个服务接口,引入TCC后可能要改造成3种逻辑:

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

注意:在设计TCC事务时,接口的Cancel和Confirm操作都必须满足幂等设计。

3.1 框架选型

TCC框架的可供选择余地比较少,目前相对比较成熟的是阿里开源的分布式事务框架seata(Seata并不完全是一个TCC事务框架),这个框架是经历过阿里生产环境的大量考验,同时也支持dubbo、spring cloud。

3.2 优点

跟2PC比起来,实现以及流程相对简单了一些,但数据的一致性比2PC也要差一些,当然性能也可以得到提升。

3.3 缺点

TCC模型对业务的侵入性太强,事务回滚实际上就是自己写业务代码来进行回滚和补偿,改造的难度大。一般来说支付、交易等核心业务场景,可能会用TCC来严格保证分布式事务的一致性,要么全部成功,要么全部自动回滚。这些业务场景都是整个公司的核心业务有,比如银行核心主机的账务系统,不容半点差池。

但是,在一般的业务场景下,尽量别没事就用TCC作为分布式事务的解决方案,因为自己手写回滚/补偿逻辑,会造成业务代码臃肿且很难维护。


Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。

它的内容包括:

  • 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
  • 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
  • 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
  • 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
  • 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
  • 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
  • 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
  • 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw

目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:

想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询

同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。

阅读全文