TCC分布式事务简介!

TCC将事务过程分为Try(尝试)、Confirm(确认)和Cancel(取消)三个阶段。

每个阶段由业务代码控制,避免了长事务的问题,从而提高了性能。

img

Try阶段

  • 尝试执行业务并完成所有业务检查,预留业务资源。

Confirm和Cancel阶段:这两个操作是互斥的,只可以选择其中一个。

  • Confirm操作是确认提交,执行业务操作,不进行其他业务检查,只使用Try阶段预留的业务资源。
  • Cancel操作在业务执行错误需要回滚的情况下执行,释放预留的资源。

Try 阶段失败可以 Cancel,如果 Confirm 和 Cancel 阶段失败了呢?

TCC事务模型中会使用事务日志来记录Try、Confirm和Cancel阶段的操作。

如果在Confirm或Cancel阶段发生错误,系统会进行重试操作。

因此,这两个阶段需要支持幂等性,以确保多次执行的结果与一次执行的结果相同。

如果重试操作失败,就需要人工介入来进行恢复和处理。

TCC的缺点:

TCC对微服务的侵入性较强,需要对业务系统进行改造。

每个分支的业务逻辑都需要实现try、confirm和cancel操作,并且confirm和cancel操作必须保证幂等性。

TCC的事务管理器需要记录事务日志,这也会带来一定的性能损耗。

与2PC/XA两阶段提交的区别:

2PC/XA关注数据库层面的强一致性,持有数据库锁。

而TCC关注业务层面的最终一致性,不涉及加锁,并且将相关的处理从数据库转移到业务中,实现跨数据库的事务。

空回滚问题:

在 try 阶段服务 发生了故障,try 阶段在不考虑重试的情况下,全局事务必须要走向结束状态。

这样就需要在服务上执行一次 cancel 操作,这样就空跑了一次回滚操作。

解决办法:

  • 第一阶段 Try 方法里会插入一条记录(事务记录表),表示一阶段执行了。

  • Cancel 接口里读取该记录,如果该记录存在,则正常回滚,如果该记录不存在,则是空回滚。

防悬挂控制:

在调用TCC服务的一阶段Try操作时,可能会出现因网络拥堵而导致的超时,此时触发二阶段回滚,调用TCC服务的Cancel操作。

在此之后,拥堵在网络上的一阶段Try数据包被TCC服务收到,出现了二阶段Cancel请求比一阶段Try请求先执行的情况。

解决思路:

  • 如果二阶段执行完成,那一阶段就不能再继续执行。

  • 在执行一阶段事务时判断在该全局事务下,事务记录表中是否已经有二阶段事务记录,如果有则不执行Try。