实战!阿里神器 Seata 实现 TCC模式 解决分布式事务,真香(五)

love374
发布于 2022-7-12 17:05
浏览
0收藏

 

2、confirm方法

实战!阿里神器 Seata 实现 TCC模式 解决分布式事务,真香(五)-鸿蒙开发者社区

 confirm方法

①处的代码从幂等工具类中根据当前类和全局事务ID获取值,由于try阶段执行成功会向其中添加值,confirm方法执行成功会移出这个值,因此在confirm开头判断这个值是否存在就起到了幂等效果,防止重试的效果。

⑥处的代码从幂等工具类中移出try方法中添加的值。

②处的代码是从BusinessActionContext中获取try方法中的入参。

③处的代码是释放掉冻结的库存

④处的代码是修改订单的状态为已完成。

“注意:1. 开启本地事务  2. 注意返回值,返回false时将会重试”


3、cancel方法

实战!阿里神器 Seata 实现 TCC模式 解决分布式事务,真香(五)-鸿蒙开发者社区

 cancel方法

①处的代码是向事务日志记录表中插入一条数据,标记当前事务进入cancel方法,用来防止悬挂,这个和try方法中的①处的代码相呼应。

②处的代码是为了防止幂等和空回滚,因为只有当try方法中执行成功幂等工具类中对应的当前类和全局事务ID才会存储该值。这样既防止了幂等,也防止了空回滚。

③处的代码恢复冻结的库存。

④处的代码删除这笔订单

⑤处的代码是移出幂等工具类当前类和全局事务ID对应的值。

 

3、如何防止TCC模型的三个异常?
实现方法有很多,有些案例是全部使用事务日志表记录当前的状态,这样完美的解决了幂等、空回滚、悬挂的问题。

陈某这里为了方便,使用了两种方案,如下:

1、幂等、空回滚

使用了一个幂等工具类,其中是个Map,key为当前类和全局事务ID,value是时间戳。

代码如下:

 实战!阿里神器 Seata 实现 TCC模式 解决分布式事务,真香(五)-鸿蒙开发者社区
思路如下:

  1. 在try方法最后使用幂等工具类中的add方法添加值
  2. 在confirm、cancel方法中使用幂等工具类中的remove方法移出值
  3. 在confirm、cancel方法中使用幂等工具类中get方法获取值,如果为空,则表示已经执行过了,直接返回true,这样既防止了幂等,也防止了空回滚。


2、悬挂

悬挂的实现依靠的是事务日志表,表结构如下:

CREATE TABLE `transactional_record` (
  `id` bigint(11) NOT NULL AUTO_INCREMENT,
  `xid` varchar(100) NOT NULL,
  `status` int(1) DEFAULT NULL COMMENT '1. try  2 commit 3 cancel ',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

其中的xid是全局事务ID,status是事务的状态。

“其他的字段自己可以扩展”


解决悬挂问题的逻辑如下:

  1. cancel方法中将当前全局事务ID记录到事务日志表中,状态为cancel
  2. try方法执行资源操作前检查事务日志表中当前全局事务ID是否已经是cancel状态


4、创建订单的业务方法
上面只是完成了TCC的三个方法,主业务事务发起方还未提供,代码如下:

 实战!阿里神器 Seata 实现 TCC模式 解决分布式事务,真香(五)-鸿蒙开发者社区
@GlobalTransactional这个注解开启了全局事务,是事务的发起方。

内部直接调用的TCC的try方法。

 

5、其他的配置
以上只是列出了关键的步骤,剩余其他的配置自己根据案例源码完善,如下:

  1. 接口测试
  2. 整合nacos
  3. 整合feign
  4. 整合seata,TCC模式中的配置和AT模式的Seata配置相同
    “注意:一定要配置Seata的事务组tx-service-group,配置方法见之前的文章。”


6、总结
TCC事务模型相对来说比较简单的一种,有兴趣的可以下载源码试试。

 

文章转自公众号:码猿技术专栏

标签
已于2022-7-12 17:05:43修改
收藏
回复
举报
回复
    相关推荐