分布式事务解决方案 -- TCC 笔记

技术 · 2021-08-13

TCC 一种成熟的分布式事务解决方案,可用于解决跨库操作的数据一致性问题。
TCC 是 Try - Confirm - Cancel 缩写,TCC 事务与传统的数据库事务不同,它存在于业务层面,由系统业务逻辑(事务协调器),进行事务控制。

TCC 将原业务服务,拆分为了三个操作。可将这三个操作,对应想象成三个方法,每个方法里有不同的业务代码。

  1. Try:检查预留资源
  2. Confirm:业务执行
  3. Cancel:回撤 Try 里执行的操作

Try

在 TCC 中,这是一个初步操作,从业务逻辑上来说,这只是检查资源(数据是否正确或业务上是否可执行等)的操作,真正执行实际业务更改是在 Confirm 中。也就是说,Try 操作过后,与后续执行的 Confirm 操作一起(Try - Confirm),才真正构成一个完整的业务逻辑。但如果 Try 操作出现异常,则会执行 Cancel 操作。(Try - Cancel)。
TCC服务需要保证Try操作成功之后,Confirm操作一定能成功。

Confirm

是对 Try 操作的一个补充。当 TCC事务管理器 决定 commit 全局事务时,就会逐个执行 Try 操作指定的 Confirm 操作,将 Try 未完成的事项最终完成。

Cancel

是对 Try 操作的一个回撤。当 TCC 事务管理器决定 rollback 全局事务时,就会逐个执行 Try 操作指定的 Cancel 操作,将 Try 操作已完成的事项全部撤回。

执行流程图

异常处理

TCC 需要注意三种异常处理分别是幂等、空回滚、资源悬挂

幂等

问题描述

网络数据包重复传输,或者异常事务的补偿执行,会导致 TCC 服务的 Try、Confirm或者Cancel操作被重复执行。

解决思路

创建事务控制表,记录事务当前执行的状态,每次执行前都查询该状态。

空回滚

问题描述

空回滚指的是 Try 未执行,Cancel 执行。

结合 TCC执行流程图 来说:

  1. 当业务应用运行至 2 调用 Try 操作 中,服务A Try 操作里的代码发起请求,等待 服务B Try 操作结果
  2. 但 服务B 此时因网络原因,无法接收 Try 操作被请求调用
  3. 此时,业务系统中的事务协调器发现 服务A 的 Try 操作迟迟未响应,认为操作失败;则会去调用 服务A 的 Cancel 操作,去回撤 Try 操作
  4. 同时也会去调用 服务B 的 Cancel 操作,去回撤 服务B 的 Try 操作。如果此时 服务B 网络正常,则会去执行 Cancel 操作。于是发生了 Try 未执行,Cancel 执行。

解决思路

我们是允许空回滚的产生的,所以我们需要在 Cancel 操作中,识别出 Try 操作是否执行。而如何识别呢?
在事务控制表中,每个服务的 Try 操作是否执行,都应有对应记录。所以可在 Cancel 操作中去读取对应服务的 Try 执行记录,来判断是否执行过 Try 操作,从而判断出本次是否为空回滚,不释放任何资源。

资源悬挂

问题描述

Cancel 比 Try 先执行。

接着空回滚流程来说:

  1. 当 服务B 执行完 Cancel 操作之后,先前 服务A 发起未抵达 服务B 的请求,被服务B接收
  2. 服务B 执行 Try 操作。于是发生了 Cancel 比 Try 先执行。

但事务协调器已经调用了 服务B 的 Cancel 操作,并且 服务B 也成功执行了 Cancel 操作。此时 服务B 中 Try 操作改变的资源将得不到 Confirm 的确认执行,或者 Cancel 回撤执行。这部分资源称为资源悬挂。

解决思路

在发生空回滚的场景下,事务控制表 记录已发生的 Cancel 控制记录,在调用 Try 时,判断是否存在此记录。

业务数据可见性控制

TCC服务的一阶段Try操作会做资源的预留,在二阶段操作执行之前,如果其他事务需要读取被预留的资源数据,那么处于中间状态的业务数据该如何向用户展示,需要业务在实现时考虑清楚;通常的设计原则是 “宁可不展示、少展示,也不多展示、错展示”。

业务数据并发访问控制

TCC服务的一阶段Try操作预留资源之后,在二阶段操作执行之前,预留的资源都不会被释放;如果此时其他分布式事务修改这些业务资源,会出现分布式事务的并发问题;
在实现TCC服务时,需要考虑业务数据的并发控制,尽量将逻辑锁粒度降到最低,以最大限度的提高分布式事务的并发性。

https://houbb.github.io/2018/09/02/sql-distribute-transaction-tcc
http://lingo0.github.io/2018/10/15/TCC-transaction学习/
https://www.cnblogs.com/haizai/p/11938823.html
https://cloud.tencent.com/developer/article/1786144
https://zhuanlan.zhihu.com/p/39575038

微服务 编程
Theme Jasmine by Kent Liao