TCC是Try、Confirm、Cancel三个词语的缩写,TCC要求每个分支事务实现三个操作:预处理Try、确认Confirm、撤销Cancel。Try操作做业务检查及资源预留,Confirm做业务确认操作,Cancel实现一个与Try相反的操作即回滚操作。TM首先发起所有的分支事务的try操作,任何一个分支事务的try操作执行失败,TM将会发起所有分支事务的Cancel操作,若try操作全部成功,TM将会发起所有分支事务的Confirm操作,其中Confirm/Cancel操作若执行失败,TM会进行重试。
分支事务成功:
分支事务失败:
TCC分为三个阶段:
- Try 阶段是做业务检查(一致性)及资源预留(隔离),此阶段仅是一个初步操作,它和后续的Confirm 一起才能真正构成一个完整的业务逻辑。
- Confirm 阶段是做确认提交,Try阶段所有分支事务执行成功后开始执行 Confirm。通常情况下,采用TCC则认为 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。若Confirm阶段真的出错了,需引入重试机制或人工处理。
- Cancel 阶段是在业务执行错误需要回滚的状态下执行分支事务的业务取消,预留资源释放。通常情况下,采用TCC则认为Cancel阶段也是一定成功的。若Cancel阶段真的出错了,需引入重试机制或人工处理。
- TM事务管理器
TM事务管理器可以实现为独立的服务,也可以让全局事务发起方充当TM的角色,TM独立出来是为了成为公用组件,是为了考虑系统结构和软件复用。
TM在发起全局事务时生成全局事务记录,全局事务ID贯穿整个分布式事务调用链条,用来记录事务上下文,追踪和记录状态,由于Confirm 和cancel失败需进行重试,因此需要实现为幂等,幂等性是指同一个操作无论请求多少次,其结果都相同。
2PC与TCC的区别
2PC是针对是资源层面的(这里的资源包括数据库、消息队列等)事务操作,他的协调者和参与者分别是事务管理器和资源管理器。关注的是多个数据源和数据副本之间的同步,为了保证强一致性,在整个两阶段包在一个大事务中,会一直持有资源的锁。典型的例子如Mysql的先写Redo日志再写BinLog就是两阶段的提交。而像Springboot开发者只需要加个@Transactional注解即可,无需关心两阶段提交的细节。
TCC是针对业务应用程序层的,协调者是应用程序,参与者也是应用程序。关注的是应用之间数据的协调。对应的锁定释放逻辑包括幂等逻辑都需要开发者实现。
TCC的缺点:
应用侵入性强:TCC由于基于在业务层面,至使每个操作都需要有 try、confirm、cancel三个接口。
开发难度大:代码开发量很大,要保证数据一致性 confirm 和 cancel 接口还必须实现幂等性。