什么是TCC事务
TCC是Try、Confirm、Cancel三个词语的缩写,要求每个分支事务执行三个操作:
预处理Try:做业务检查和资源预留
确认Confirm:做业务确认
撤销Cancel:实现回滚操作
TM首先会发起所有分支事务的try操作,任何一个分支事务的try操作执行失败,TM将会发起所有分支事务的Cancel操作,若try全部成功,TM将会发起所有分支事务的confirm操作,其中,若confirm、cancel执行失败,TM会进行重试。
TCC分为三个阶段:
1)Try阶段是做业务检查(一致性)及资源预留(隔离)。
2)Confirm阶段是做确认提交,Try阶段所有分支事务执行成功开始执行confirm。
通常情况下使用TCC则认为在Confirm阶段不会出错,只要try成功,confirm一定成功。若confirm出错,则进行重试或人工处理。
3)Cancel阶段是在业务执行错误需要回滚的状态下,执行其他未失败的分支事务的取消,即预留资源的释放。
通常情况下,TCC的Cancel阶段也认为是一定成功的,若出错曾引入重试或人工处理。
TCC的实现方案
以下几个框架均支持TCC全局事务,目前阿里seata拥有较大的用户基数,github的star数也是遥遥领先,后面会逐步增加seata实战源码。
名称 | github |
---|---|
tcc-transaction | https://github.com/changmingxie/tcc-transaction |
LCN | https://github.com/codingapi/tx-lcn |
Alibaba Seata | https://github.com/seata/seata |
Hmily | https://github.com/yu199195/hmily |
ByteTCC | https://github.com/liuyangming/ByteTCC |
TCC的空回滚解决了什么问题?
在Try阶段,假设对服务A发送Try请求,由于网络原因导致网络超时,此时协调器收到网络超时的响应,需要在第二步进行cancel操作。可是服务A在Try阶段根本没有执行成功,这样就导致了数据不一致。
解决问题的关键是如何在Try阶段识别出服务A是否执行成功了,如果成功了就执行commit,如果失败了,就执行空回滚。可以增加一张分支事务记录表,记录分支事务和全局事务id,当请求超时后可以通过此表查看分支事务,执行Try则记录,没有则走空回滚。
TCC如何解决幂等问题?
主要出现在Try阶段。在confirm或cancel前先进行查询,通过增加一张事务状态表。
更加严谨需要增加分布式锁。
TCC如何解决悬挂问题?
由于超时等原因,cancel比try先执行,就是悬挂问题。
解决方案增加分支事务记录表,先去查询,如果cancel已经执行,则不再执行try。