TCC分布式事务七种异常情况

2023年 10月 9日 50.7k 0

大家好,我是小趴菜,上篇文章我们了解了下TCC的5种编程模型,也知道了在try,confirm,cancel三个阶段都应该做什么事,今天我们来学习下在整个TCC模型过程中可能会出现的几种异常情况

TCC标准编程模型

image.png

异常一:try阶段异常

在try阶段异常之后,就会执行cancel阶段,此时cancel阶段是一定要保证成功的,如果cancel阶段没有执行成功,那么就要进行重试

异常二:cancel阶段异常

其实这个异常的处理方式和异常一是一样的,失败了就重试,如果一直重试失败,那么就要进行人工干预

异常三:confirm提交异常

try阶段成功了,那么confirm一定要成功,如果失败了,那么就要进行重试,重试多次还未成功,那么就要进行人工干预

但是这里重试要注意,因为在confirm阶段有二步数据库操作,如果扣冻结张三20元成功了,但是李四加20元失败了,这时候重试就要做判断,看张三扣减20元是否之前已经操作成功了,如果操作成功了,就不要再次进行扣减冻结的操作

image.png

异常四:本地事务与TCC事务冲突

在try阶段我们添加了一个本地事务,如果这时候try阶段异常,那么本地事务就会回滚,所以这时候冻结张三20元的操作就会回滚,也就不会被冻结。那么这时候try阶段异常了,就会执行cancel阶段进行回滚

在cancel阶段,我们会还张三冻结的20元,这时候如果cancel执行成功,那么张三的金额就会多出20元,就会造成数据的不一致,所以一般不要加本地事务

@Transaction(rollback=Exception.class)
@Hmily(comfirmMethod="confirmMethod",cancelMethod="cancelMethod")
public void try() {
  //查询张三余额信息  
  Account account = accountMapper.selectByUserId(1);
  //冻结张三20元
  account.setDJAccount(20);
  accountMapper.updateById(account);
}

image.png

异常五:空回滚

为什么会有空回滚的异常呢?
比如我们在执行try阶段的时候,由于超时了,导致TCC就去执行cancel阶段了,但是这时候try阶段还没有执行,也就是try阶段还没有冻结张三20元,这时候就造成了空回滚。

这时候我们需要引入其它手段,比如增加一张日志表,在回滚的时候,判断一下这是事务有没有执行try阶段,也就是这个事务有没有执行过try阶段,如果没有就不要执行cancel阶段的操作了。

image.png

异常六:第二阶段重复提交

第二阶段包括confirm,cancel,为什么会有重复提交呢? 因为我们不能保证confirm阶段或者cancel阶段一定能成功,如果不成功那么我们就要进行重试,

举个例子,在confirm阶段有二步数据库操作,假设扣减张三冻结20元成功,但是李四加20元失败了,这时候我们就要进行重试,但是重试的时候我们扣减张三冻结的20元已经操作成功了,所以不需要再次扣减了,所以我们要做好类似去重的操作,之前操作成功的就不要再次进行操作了

image.png

异常七:防悬挂

cancel阶段比try阶段先执行,由于网络原因导致try阶段超时,这时候就会执行cancel阶段操作,等cancel阶段执行完了,这时候try才执行,虽然事务失败了,但是这个事务已经结束了,所以这时候的try方法一定不能执行

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论