1、通用性TCC技术方案
其实所谓的TCC思想,画一张图来说,大致说起来就很简单,我们就用自己的流量充值中心来举个例子好了,你要是不考虑具体的技术实现的话,大概来说呢,相当于就是下面这样的思路:
(1)主业务服务:相当于流量充值中心的服务,他就是TCC事务的主控服务,主要控制的服务,负责整个分布式事务的编排和管理,执行,回滚,都是他来控制 (2)从业务服务:相当于我们的资金服务、订单服务、积分服务、抽奖服务、流量券服务,主要就是提供了3个接口,try-confirm-cancel,try接口里是锁定资源,confirm是业务逻辑,cancel是回滚逻辑 (3)业务活动管理器:管理具体的分布式事务的状态,分布式事务中各个服务对应的子事务的状态,包括就是他会负责去触发各个从业务服务的confirm和cancel接口的执行和调用。。。
(1)try阶段,资源的锁定,先冻结掉用户的账户资金,将一部分资金转出到冻结资金字段里去;可以创建一个充值订单,但是状态是“交易中” (2)confirm阶段,就是将用户的冻结资金口减掉,转移到商户的账户里去;同时将充值订单的状态修改为“交易成功”;完成抽奖机会、积分、流量券的新增 (3)cancel阶段,try阶段任何一个服务有问题的话,那么就cancel掉,相当于是将冻结的资金还回去,将订单状态修改为“交易失败”;如果confirm阶段任何一个服务有问题的话,也是cancel掉,相当于是将商户账户里的资金还到用户账户里去,同时将订单的状态修改为“交易失败”
有一张比较经典的图,就是主业务服务->数据库,然后几个从业务服务->数据库,接着主业务服务会访问业务活动管理器(有活动日志),主业务服务发起执行try,然后主业务服务通知业务活动管理器,业务活动管理器再通知各个从业务发起confirm或者是cancel操作,可以把这张图给体现一下
这里主业务服务其实就是总控整套逻辑的,然后从业务服务就是干活儿的,业务活动管理器主要是记录整个分布式事务活动状态的,这个还是挺有必要的吧,这样保存分布式事务进行过程中的各种状态才可以啊,兄弟!
不然分布式事务临时终端了,你系统重启,谁知道你之前跑到哪一步了啊,哥儿们!
所以他会记录整个分布式事务的状态,分布式事务里各个服务代表的子事务的状态,而且他是负责在提交分布式事务的时候,调用各个从业务服务的confirm接口的,如果出问题的话也是他调用各个从业务服务的cancel接口的
所以说这里的一个执行流程和步骤大概是这样子的:
(1)主业务服务会先在本地开启一个本地事务(这个本地事务说白了,就是你的主业务服务是不是也可能会干点儿什么事儿) (2)主业务服务向业务活动管理器申请启动一个分布式事务活动,主业务服务向业务活动管理器注册各个从业务活动 (3)接着主业务服务负责调用各个从业务服务的try接口 (4)如果所有从业务服务的try接口都调用成功的话,那么主业务服务就提交本地事务,然后通知业务活动管理器调用各个从业务服务的confirm接口 (5)如果有某个服务的try接口调用失败的话,那么主业务服务回滚本地事务,然后通知业务活动管理器调用各个从业务服务的cancel接口 (6)如果主业务服务触发了confirm操作,但是如果confirm过程中有失败,那么也会让业务活动管理器通知各个从业务服务cancel (7)最后分布式事务结束
2、异步确保型TCC技术方案
如果要接入到一个TCC分布式事务中来,从业务服务必须改造自己的接口,本来就是一个接口,现在要新增两个接口,try接口,cancel接口。改造起来比较麻烦
这个大概来说就是把之前的通用型TCC方案给改造了一下,就是在主业务服务和从业务服务之间加了一个可靠消息服务,但是这个可靠消息服务可不是在请求什么MQ之类的东西,而是将消息放在数据库里的
大致来说呢,就是主业务服务的try、confirm和canel操作都调用可靠消息服务,然后可靠消息服务在try阶段插入一条消息到本地数据库;接着主业务服务执行confirm操作,可靠消息服务就是根据之前的消息,调用从业务服务实际的业务接口;如果要是这个调用失败的话,那么主业务服务发起cancel,可靠消息服务删除自己本地的消息即可
这种方案大家可以看到,其实说白了最大的优点,就是不需要从业务服务配合改造,提供try、confirm和cancel三个接口了,本来人家可能就一个接口,现在你楞是要求人家提供三个接口,真尴尬
那要是用了这种方案,就可以用可靠消息服务替代各个从业务服务提供TCC三个接口了
3、补偿性TCC解决方案
这个其实是跟通用型的TCC方案类似的,只不过从业务服务就提供俩接口就ok了,Do和Compensate,就是执行接口和补偿接口,这种方案的好处就是折中一下了,不需要从业务服务改造出来一个T接口,就是锁定资源的接口,只需要加一个补偿接口,如果业务逻辑执行失败之后,进行补偿
这样就可以少做一个接口了,但是因为没有做资源的一个锁定,那么大家需要自己注意类似资金转账的余额检查之类的事儿了,还有就是补偿的时候,因为你没做资源锁定,所以要注意一下补偿机制是否一定会成功
其实说实话,这个补偿性的TCC方案还是蛮不错挺有吸引力的
Do接口,Compensate接口,不要try接口,不要锁定资源,直接执行业务逻辑,如果有失败就调用Compensate接口,补偿接口,回滚刚才的操作