分布式事务——TCC 原理

概念

TCC 又称补偿事务。其核心思想是: " 针对每个操作都要注册一个与其对应的确认和补偿(撤销)操作 "。它分为三个操作:

Try 阶段:主要是对业务系统做检测及资源预留。

Confirm 阶段:确认执行业务操作。

Cancel 阶段:取消执行业务操作。

TCC 对应 TryConfirmCancel 三种操作可以理解成关系型数据库事务的三种操作:DML、Commit、Rollback。

 

在一个跨应用的业务操作中

Try:Try 操作是先把多个应用中的 业务资源预留 和 锁定,为后续的确认打下基础,类似的,DML 操作要锁定数据库记录行,持有数据库资源。

Confirm:Confirm 操作是在 Try 操作中涉及的所有应用均成功之后进行确认,使用预留的业务资源,和 Commit 类似。

Cancel:Cancel 则是当 Try 操作中涉及的所有应用没有全部成功,需要将已成功的应用进行取消即 Rollback 。其中 Confirm  Cancel 操作是一对反向业务操作。

 

TCC 的具体原理如下:

分布式事务——TCC 原理

从图中我们可以明显看到 Confirm  Cancel 操作是一对反向业务操作即要 Try 返回成功执行 Confirm要么 Try 返回失败执行 Cancel 操作。

分布式事务协调者:管理控制整个业务活动,包括记录维护 TCC 全局事务的事务状态和每个从业务服务的子事务状态,并在业务活动提交时确认所有的 TCC 型操作的 Confirm 操作,在业务活动取消时调用所有 TCC 型操作的 Cancel 操作。

 

 

举例

例子A服务 转 30 块钱、B服务 转 50 块钱,一起到 C 服务上。

Try(尝试执行业务):完成所有业务检查,检查 A、B、C 的帐户状态是否正常,帐户A 的余额是否不少于 30 元,帐户B 的余额是否不少于 50 元。预留必须的业务资源(准隔离性帐户A 的冻结金额增加 30 元,帐户B 的冻结金额增加 50 元,这样就保证不会出现其他并发进程扣减了这两个帐户的余额而导致在后续的真正转帐操作过程中,帐户 A 和 B 的可用余额不够的情况。

Confirm(确认执行业务):真正执行业务,如果 Try 阶段帐户 A、B、C 状态正常,且帐 AB 余额够用,则执行 帐户A 给 账户C 转账 30 元、帐户B 账户C 转账 50 元的转帐操作。这时已经不需要做任何业务检查,Try 阶段已经完成了业务检查。只使用 Try 阶段预留的业务资源,即 Try 阶段 帐户A 和 帐户B 冻结的金额。

Cancel(取消执行业务):释放 Try 阶段预留的业务资源,如果 Try 阶段部分成功,比如 帐户A 的余额够用,且冻结相应金额成功,帐户B 的余额不够而冻结失败,则需要对 帐户A  Cancel 操作,将 帐户A 被冻结的金额解冻掉。

 

 

TCC 和 2PC 比较

2PC 是资源层面的分布式事务,强一致性,在两阶段提交的整个过程中,一直会持有资源的锁。

XA 事务中的两阶段提交内部过程是对开发者屏蔽的,事务管理器在两阶段提交过程中,从 prepare  commit/rollback 过程中,资源实际上一直都是被加锁的。如果有其他人需要更新这两条记录,那么就必须等待锁释放。

 

TCC 是业务层面的分布式事务,最终一致性,不会一直持有资源的锁。

当执行 Try 接口的时候,已经把所需的资源给预扣了,比如上面举例的 A服务 已经预扣 30 元,B服务 已经预扣 50 元,它是由 Try 接口实现,这样就保证不会出现其他并发进程扣减了这两个帐户的余额而导致在后续的真正转帐操作过程中,帐户 A 和 B 的可用余额不够的情况,同时保证不会一直锁住整个资源。

TCC中的两阶段提交并没有对开发者完全屏蔽,也就是说从代码层面,开发者是可以感受到两阶段提交的存在。

(1) Try 过程的本地事务,是保证资源预留的业务逻辑的正确性。

(2) Confirm/Cancel 执行的本地事务逻辑确认/取消预留资源,以保证最终一致性,也就是所谓的补偿型事务

由于是多个独立的本地事务,因此不会对资源一直加锁。

 

 

原文:https://www.cnblogs.com/qdhxhz/p/11172585.html