标签:回滚 之间 支付宝 commit 自己 余额 进入 应用层 需要
在之前分布式一致性问题博客中提到了关于分布式事务一致性问题的两种解决方案,2PC和3PC,2PC用在数据库层面解决数据库之间的分布式事务;
因此实际应用中往往不会采用这两个方案,下面说一下其他的解决方案
TCC:
TCC是支付宝提出的分布式事务解决方案,是try、confirm、cancel的简写。TCC是应用层面的分布式系统的分布式事务解决方案。
服务设计:
每个分布式事务的参与者都需要实现3个接口:try、confirm、cancel。try对应2PC的preCommit,confirm负责事务提交,cancel负责事务回滚。
TCC分为2个阶段:
1)准备阶段
调用方调用各个服务的try接口,各个服务执行资源检查和锁定,看自己是否有能力完成,如果允许,则锁定资源
2)提交阶段
如果各个服务的try接口都返回了yes,则进入提交阶段,调用方调用各个服务的confirm接口,然后各个服务对try阶段锁定的资源进行处理。
如果try阶段有一方返回了no,或者超时,调用方调用各个服务的cancel接口,释放锁定的资源。
对于异常情况,不管是confirm还是cancel失败了,处理方法就是不断重试。
流程示例:
以转账为例,有2两个服务,扣钱服务、加钱服务,都各自实现try、confirm、cancel接口。
需求:现在账号A要给账号B转30元
阶段1:准备阶段
调用者调用2个服务的try接口。
1):扣钱服务的try接口对A中的余额进行验证,如果可用余额不少于30元,则冻结30元,返回yes,否则返回no。
2):加钱服务的try接口对B账号进行校验,如是否合法可用状态,是则返回yes,否则返回no
这个阶段保证了扣钱可扣,加钱可加
阶段2:提交阶段
两个服务的try接口都返回了yes,调用者调用2个服务的confirm接口。扣钱服务实际扣减A的30元,加钱服务实际给B加30元
try接口如果有返回no或者超时的,调用者调用2个服务的cancel接口,扣钱服务解冻A的30元,加钱服务什么也不用做。
异常控制:
下面是典型的异常情况
1、空回滚
现象是try没执行就调用了cancel,例如在某些异常情况下,调用try时出现异常,try接口实际没有被调用,那么就没有返回yes;按照正常流程进入第二
阶段,调用cancel接口,这就造成了空回滚。
解决方案:让cancel能够识别出这是一个空回滚,可以记录事务执行状态,cancel中判断try是否执行了
2、幂等
提交阶段可能会重复调用confirm和cancel,所以要实现幂等,保证多次执行效果一致。
解决方案:记录事务执行状态,如果执行过了,就不再执行
3、悬挂
现象是先执行了cancel,后执行了try,造成资源没人释放。例如调用try时网络拥堵超时,被认为失败啊,然后调用cancel,这时事务相当于结束了,但后来
网络好之后try开始执行了,锁定了相关资源,因为事务已经结束,confirm和cancel都不会再调用,造成资源悬挂,无法释放
解决方案:还是记录事务执行状态,try执行时判断cancel是否执行了
总结
优点:可靠性高,实用性高
缺点:开发复杂度高,需要多次DB操作,性能有一定损耗。
标签:回滚 之间 支付宝 commit 自己 余额 进入 应用层 需要
原文地址:https://www.cnblogs.com/yangyongjie/p/11008038.html