什么是TCC,TCC是Try、Confirm、Cancel这三个词的缩写,由PatHelland于2007年首次发表名为《Life beyond Distributed Transactions:an Apostate’s Opinion》的论文呈现。TCC组成TCC分为3个阶段Try阶段:尝试执行,完成所有业务检查(一致性),预留必要的业务资源(准隔离)Confirm阶段:如果Try的所有分支都成功,则进入Confirm阶段。Confirm实际执行业务,不做任何业务检查,只使用Try阶段预留的业务资源。Cancel阶段:如果所有分支中有一个Try失败,则进入Cancel阶段。Cancel释放Try阶段预留的业务资源。在TCC分布式事务中,有3个角色,与经典的XA分布式事务相同:AP/应用程序,发起全局事务,定义全局事务中包含哪些事务分支RM/资源管理器,负责管理分支事务的各种资源TM/transactionmanager负责协调全局事务的正确执行,包括Confirm和Cancel的执行,以及处理网络异常。如果我们要进行一个类似银行跨行转账的业务,分别在不同的微服务中转出(TransOut)和转入(TransIn),一个成功完成的TCC交易的典型时序图如下:TCC网络异常期间TCC整个全局事务过程,可能会出现各种网络异常,典型的是空回滚、幂等、挂起,因为TCC的异常情况和SAGA、可靠消息等事务模式类似,所以我们把所有的异常解决方案放在子-本文的交易壁垒链接《分布式事务最经典的七种解决方案》来讲解TCC的做法。TCC事务的具体开发目前可??以使用TCC的开源框架,主要是Java语言,其中seata是代表。我们的例子使用的是nodejs,使用的分布式事务框架是dtm,非常优雅的支持分布式事务。下面详细解释一下TCC的组成。下面来写具体的Try/Confirm/Cancel处理函数router.post('/api/TransOutTry',(ctx,next)=>{console.log("TransOutTry")ctx.body={result:"SUCCESS"}}).post('/api/TransOutConfirm',(ctx,next)=>{console.log("TransOutConfirm")ctx.body={result:"SUCCESS"}}).post('/api/TransOutCancel',(ctx,next)=>{console.log("TransOutCancel")ctx.body={result:"SUCCESS"}}).post('/api/TransInTry',(ctx,next)=>{console.log("TransInTry")ctx.body={result:"SUCCESS"}}).post('/api/TransInConfirm',(ctx,next)=>{console.log("TransInConfirm")ctx.body={result:"SUCCESS"}}).post('/api/TransInCancel',(ctx,next)=>{console.log("TransInCancel")ctx.body={result:"SUCCESS"}})此时,各个子事务的处理函数都已经OK了,然后启动TCC事务,分支调用asyncfunctionFireTcc(){letdtm="http://localhost:8080/api/dtmsvr"//dtm服务地址letsvc="http://localhost:4005/api"//本地服务前缀//开启一个tcc事务,在第二个参数中,编写全局事务的逻辑awaitdtmcli.tccGlobalTransaction(dtm,async(t)=>{letreq={amount:30}//子事务需要的负载console.log("callingtransout")//注册事务分支并调用分支Trayawaitt.callBranch(req,svc+"/TransOutTry",svc+"/TransOutConfirm",svc+"/TransOutCancel")console.log("callingtransin")//注册事务分支并调用Trayawaitt.callBranch(req,svc+"/TransInTry",svc+"/TransInConfirm",svc+"/TransInCancel")})}至此,一个完整的TCC分布式事务就写完了。如果想运行成功的例子,请参考这个例子yedf/dtmcli-node-sample,运行很简单#deploymentstartdtm#requiresdockerversion18orabovegitclonehttps://github.com/yedf/dtmcddtmdocker-composeup#启动另一个命令行gitclonehttps://github.com/yedf/dtmcli-node-samplecddtmcli-node-samplenpminstallnode.TCC回滚银行发现用户2的账户异常,返回失败怎么办银行将金额转给用户2?我们给出一个事务失败交互的时序图。这个和成功的TCC的区别在于,当一个子事务失败时,全局事务随后回滚,调用每个子事务的Cancel操作,保证全局事务全部回滚。小结在本文中,我们介绍了TCC的理论知识,并通过一个例子,给出了一个完整的TCC事务编写流程,涵盖了正常成功完成和成功回滚的情况。相信读者通过本文对TCC有了更深入的了解。更全面的分布式事务知识请参考《分布式事务最经典的七种解决方案》本文所用示例摘自yedf/dtm,支持多种事务模式:TCC、SAGA、XA,事务消息跨语言支持,支持golang,python,Java,PHP,nodejs等语言的客户端,参考各语言的SDK。提供子事务屏障功能,优雅解决幂等、挂起、空值补偿等问题。看完这篇干货,欢迎大家访问https://github.com/yedf/dtm项目,给个star支持!
