当前位置: 首页 > news >正文

大白话 Seata 分布式事务浅析,详解TCC模式

大家好,我是此林。

说到分布式事务,第一时间想到 Seata,它支持多种事务模型,比如:XA模式、AT模式、TCC模式、Saga模式(长事务)。

其中 TCC 模式是高性能分布式事务解决方案,适用于核心系统等对 性能有很高要求的场景

不过,相对于 XA 和 AT 无业务入侵的即插即用模式,TCC 是一种 侵入式 的分布式事务解决方案,需要业务系统自行实现 Try,Confirm,Cancel 三个操作,对业务系统有着非常大的入侵性,设计相对复杂。

一、分布式事务

这里贴一张官网的图,其实也就是 Seata 分布式事务的 领域模型,无论是哪种模式(XA、AT、TCC、Saga),都遵循这个模型。

从图中可以看到,三个角色的覆盖级别是:TC > TM > RM

对于Seata 中的

  • TC(Transaction Coordinator)
  • TM(Transaction Manager)
  • RM(Resource Manager)

三者的关系,比难以理解,我们用大白话+代码演示的形式展示。

1. TC事务协调者,我们如果想使用 Seata,是不是需要独立不是 Seata 服务?那这个 Seata 可以简单理解为事务协调中心,即 TC

2. TM事务管理器,可以简单理解为就是 @GlobalTransactional 注解,即全局事务

3. RM资源管理器,这个层级最低,可以理解为标注了@GlobalTransactional 注解的方法下的远程调用 RPC/Feigin 服务分支事务

我们创建一个电商业务,用户下单时:

  1. 扣减库存(库存服务);

  2. 创建订单(订单服务);

  3. 资金支付(账户服务)。

@Service
public class OrderService {@Autowiredprivate InventoryService inventoryService;@Autowiredprivate AccountService accountService;@Autowiredprivate OrderMapper orderMapper;// 这里就是 TM@GlobalTransactional(name = "create_order_tx", rollbackFor = Exception.class)public void createOrder(String userId, String productId, int amount) {// 调用 RM#1 扣减库存inventoryService.deduct(productId, amount);// 调用 RM#2 扣减账户余额accountService.debit(userId, amount * 10);// 插入订单记录(当前服务自己就是 RM)orderMapper.insert(new Order(userId, productId, amount));}
}

可以看到,TM(事务发起方)下,会调用 RM#1 扣减库存,调用 RM#2 扣减账户余额,插入订单记录(当前服务自己就是 RM)。

这样一看是不是关系理清很多了?

二、什么是 TCC 模式?

TCC(Try-Confirm-Cancel)是 Seata 支持的一种 侵入式的分布式事务解决方案,最早由蚂蚁金服提出。

一个分布式的全局事务,整体是 两阶段提交 的模型。全局事务是由若干分支事务组成的,分支事务要满足 两阶段提交 的模型要求,即需要每个分支事务都具备自己的:

  • 一阶段 prepare 行为
  • 二阶段 commit 或 rollback 行为

AT 模式基于 支持本地 ACID 事务 的 关系型数据库

  • 一阶段 prepare 行为:在本地事务中,一并提交业务数据更新和相应回滚日志记录。
  • 二阶段 commit 行为:马上成功结束,自动 异步批量清理回滚日志。
  • 二阶段 rollback 行为:通过回滚日志,自动 生成补偿操作,完成数据回滚。

相应的,TCC 模式,不依赖于底层数据资源的事务支持:

  • 一阶段 prepare 行为:调用 自定义 的 prepare 逻辑。
  • 二阶段 commit 行为:调用 自定义 的 commit 逻辑。
  • 二阶段 rollback 行为:调用 自定义 的 rollback 逻辑。

所谓 TCC 模式,是指支持把 自定义 的分支事务纳入到全局事务的管理中。

所以为什么说 TCC 侵入性高?

TCC 服务化的资源管理方式,不依赖于数据库事务,而是由业务系统显式地控制这三个阶段。

XA 和 AT 模式直接使用数据源代理来屏蔽分布式事务细节。

TCC下,业务方需要自行定义 TCC 资源的“准备”、“提交”和“回滚” 。

TCC 三个阶段的含义

阶段说明
Try尝试执行业务,预留必要资源(如扣减库存、锁定额度)
Confirm确认执行业务,真正提交资源(如减库存、扣款)
Cancel回滚业务,释放预留资源,保证幂等

三、TCC 基本使用

我们以一个下单(订单 + 库存)为例子,用 TCC 模式 简化演示。

1. TM 发起全局事务(@GlobalTransactional)

@Service
public class OrderService {@Autowiredprivate InventoryTccAction inventoryTcc;@Autowiredprivate PaymentTccAction paymentTcc;// TM 在这里@GlobalTransactionalpublic void placeOrder(String productId, int count) {inventoryTcc.prepare(null, productId, count); // RM 分支事务1paymentTcc.prepare(null, "userA", 100);       // RM 分支事务2}
}

其中 InventoryTccAction 是库存服务,PaymentTccAction 是支付服务。

2. RM1:库存服务实现 TCC 接口

public interface InventoryTccAction {@TwoPhaseBusinessAction(name = "inventoryTcc", commitMethod = "commit", rollbackMethod = "rollback")boolean prepare(BusinessActionContext ctx, @BusinessActionContextParameter(paramName = "productId") String productId, int count);boolean commit(BusinessActionContext ctx);boolean rollback(BusinessActionContext ctx);
}

3. RM 2:支付服务实现 TCC 接口

public interface PaymentTccAction {@TwoPhaseBusinessAction(name = "paymentTcc", commitMethod = "commit", rollbackMethod = "rollback")boolean prepare(BusinessActionContext ctx, @BusinessActionContextParameter(paramName = "userId") String userId, int amount);boolean commit(BusinessActionContext ctx);boolean rollback(BusinessActionContext ctx);
}

RM 业务接口中核心的注解是 @TwoPhaseBusinessAction,表示当前方法使用 TCC 模式管理事务提交,并标明了 Try,Confirm,Cancel 三个阶段。name属性,给当前事务注册了一个全局唯一的的 TCC bean name。

注意,如果 TCC 参与者是本地 bean(非远程RPC服务),本地 TCC bean 还需要在接口定义中添加 @LocalTCC 注解,比如支付服务是本地的:

@LocalTCC
public interface PaymentTccAction {@TwoPhaseBusinessAction(name = "paymentTcc", commitMethod = "commit", rollbackMethod = "rollback")boolean prepare(BusinessActionContext ctx, @BusinessActionContextParameter(paramName = "userId") String userId, int amount);boolean commit(BusinessActionContext ctx);boolean rollback(BusinessActionContext ctx);
}

4. TM、RM、TC 工作流程图 

5. 注意事项

在旧版Seata,比如小于1.3,为了让 Dubbo/Sofa 的远程调用对象支持 TCC,框架引入了一个类

具体位置:src/main/java/org/apache/seata/spring/tcc/TccAnnotationProcessor.java

@Deprecated
public class TccAnnotationProcessor implements BeanPostProcessor

这个类目前已经被标记为废弃。

那时候框架并不会自动识别是否是 TCC Bean,必须依赖 TccAnnotationProcessor 这个类来扫描注解字段并手动生成代理

不过用法上相比于现在,只不过需要在TM 发起全局事务加上@Reference 注解而已,比如:

@Reference
private PaymentTccAction paymentTcc;

TccAnnotationProcessor主要功能:

  • 在 Spring 启动时扫描 Bean 字段上的 @Reference(Dubbo)或 @SofaReference 注解。

  • 判断其字段类型的方法是否带有 @TwoPhaseBusinessAction

  • 如果带有,则通过反射为该字段注入代理对象。

  • 将该代理对象包装成 TCC RM 支持的形式,注册为资源参与者。

在新版 Seata 里,调用方不需要处理代理,Tcc advice 逻辑移动到了 RM 侧,内置支持 RM 自动识别。

今天的分享就到这里了,

我是此林,关注我吧,带你看不一样的世界!

相关文章:

  • 深度学习中常见的超参数对系统的影响
  • Bootstrap 5学习教程,从入门到精通,Bootstrap 5 入门简介(1)
  • 【创新实训个人博客】实现了新的前端界面
  • Office安装包2024版
  • Linux驱动之平台总线
  • 【拓扑排序】P6560 [SBCOI2020] 时光的流逝|普及+
  • 腾讯位置商业授权行政区划开发指南
  • [PCIe]Gen6 PAM4的功耗相比Gen5 NRZ增加了多少?
  • 35、请求处理-【源码分析】-自定义参数绑定原理
  • 6、修改和校正时间
  • 跨平台猫咪桌宠 BongoCat v0.4.0 绿色版
  • 【论文解读】Deformable DETR | Deformable Transformers for End-to-End Object Detection
  • 【目标检测】backbone究竟有何关键作用?
  • 2023年6月6级第一套第一篇
  • 设计模式——责任链设计模式(行为型)
  • YOLOv5 环境配置指南
  • CCPC dongbei 2025 I
  • 《Pytorch深度学习实践》ch2-梯度下降算法
  • 怎么样提高研发质量?
  • 小白的进阶之路系列之九----人工智能从初步到精通pytorch综合运用的讲解第二部分
  • 汕头网站设计哪里好/淘宝运营培训多少钱
  • 合肥哪家制作网站/seo高手培训
  • 坪洲网站建设/网站空间租用
  • 怎么搭建自己的网站挣钱/怎么推广游戏代理赚钱
  • 京东这样的网站是怎么做的/2023年5月疫情爆发
  • 企业网站做的公司/北京关键词优化服务