Seata之TCC模式解读
目录
基本介绍
起源
概述
案例流程分析
TCC注意事项
空回滚
幂等
悬挂
具体使用
@LocalTCC
@TwoPhaseBusinessAction
小结
基本介绍
起源
关于TCC的概念,最早是由Pat Helland于2007年发表的一篇名为《Life beyond Distributed Transactions:an Apostate’s Opinion》的论文提出。
在该论文中,TCC还是以Tentative-Confirmation-Cancellation命名。正式以Try-Confirm-Cancel作为名称的是Atomikos公司,其注册了TCC商标。
概述
TCC是Try-Confirm-Cancel的简称。
TCC模式与AT模式非常相似,每阶段都是独立事务,不同的是TCC通过人工编码来实现数据恢复。需要实现三个方法:
-
Try:资源的检测和预留。做业务检查(一致性)及资源预留(隔离),此阶段仅是一个初步操作,它和后续的Confirm 一起才能真正构成一个完整的业务逻辑。
-
Confirm:完成资源操作业务;要求 Try 成功 Confirm 一定要能成功。做确认提交,Try阶段所有分支事务执行成功后开始执行 Confirm。通常情况下,采用TCC则 认为 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。若Confirm阶段真的出错了,需引入重试机制或人工处理。
-
Cancel:预留资源释放,可以理解为try的反向操作。在业务执行错误需要回滚的状态下执行分支事务的业务取消,预留资源释放。通常情况下,采 用TCC则认为Cancel阶段也是一定成功的。若Cancel阶段真的出错了,需引入重试机制或人工处理。
TM首先发起所有的分支事务的try操作,任何一个分支事务的try操作执行失败,TM将会发起所有分支事务的Cancel操作,若try操作全部成功,TM将会发起所有分支事务的Confirm操作,其中Confirm/Cancel 操作若执行失败,TM会进行重试。
与AT模式与TCC模式的对比
| AT模式 | TCC模式 | |
| 一阶段 prepare | 在本地事务中,一并提交业务数据更新和相应回滚日志记录 | 调用 自定义的 prepare 逻辑 |
| 二阶段 commit | 马上成功结束,自动异步批量清理回滚日志 | 调用 自定义的commit 逻辑 |
| 二阶段 rollback | 通过回滚日志,自动 生成补偿操作,完成数据回滚。 | 调用 自定义的rollback 逻辑 |
| 其他 | 支持本地 ACID 事务 的 关系型数据库 | 不依赖于底层数据资源的事务支持 |
TCC支持把自定义的分支事务纳入到全局事务的管理中。
案例流程分析
假设一个扣减用户余额的业务。假设账户A原来余额是100,需要余额扣减30元。

阶段一( Try ):检查余额是否充足,如果充足则冻结金额增加30元,可用余额扣除30

总金额 = 冻结金额 + 可用金额,数量依然是100不变。事务直接提交无需等待其它事务。
阶段二(Confirm):,现在库存充足,可以提交(Confirm),则冻结金额扣减30确认可以提交,不过之前可用金额已经扣减过了,这里只要清除冻结金额就好了

阶段二(Canncel):如果库存不足,需要回滚(Cancel),则冻结金额扣减30,可用余额增加30需要回滚,那么就要释放冻结金额,恢复可用金额:

TCC注意事项
空回滚
- 在没有调用 TCC 资源 Try 方法的情况下,调用了二阶段的 Cancel 方法,Cancel 方法需要识别出这是一个空回 滚,然后直接返回成功。
- 出现原因是当一个分支事务所在服务宕机或网络异常,分支事务调用记录为失败,这个时候其实是没有执行Try阶 段,当故障恢复后,分布式事务进行回滚则会调用二阶段的Cancel方法,从而形成空回滚。
- 解决思路是关键就是要识别出这个空回滚。思路很简单就是需要知道一阶段是否执行,如果执行了,那就是正常回 滚;如果没执行,那就是空回滚。前面已经说过TM在发起全局事务时生成全局事务记录,全局事务ID贯穿整个分 布式事务调用链条。再额外增加一张分支事务记录表,其中有全局事务 ID 和分支事务 ID,第一阶段 Try 方法里会 插入一条记录,表示一阶段执行了。Cancel 接口里读取该记录,如果该记录存在,则正常回滚;如果该记录不存 在,则是空回滚。
幂等
- 为了保证TCC二阶段提交重试机制不会引发数据不一致,要求 TCC 的二阶段 Try、 Confirm 和 Cancel 接口保证幂等,这样不会重复使用或者释放资源。如果幂等控制没有做好,很有可能导致数据 不一致等严重问题。
- 解决思路在上述“分支事务记录”中增加执行状态,每次执行前都查询该状态。
悬挂
- 悬挂就是对于一个分布式事务,其二阶段 Cancel 接口比 Try 接口先执行。
- 出现原因是在 RPC 调用分支事务try时,先注册分支事务,再执行RPC调用,如果此时 RPC 调用的网络发生拥堵, 通常 RPC 调用是有超时时间的,RPC 超时以后,TM就会通知RM回滚该分布式事务,可能回滚完成后,RPC 请求 才到达参与者真正执行,而一个 Try 方法预留的业务资源,只有该分布式事务才能使用,该分布式事务第一阶段预 留的业务资源就再也没有人能够处理了,对于这种情况,我们就称为悬挂,即业务资源预留后没法继续处理。
- 解决思路是如果二阶段执行完成,那一阶段就不能再继续执行。在执行一阶段事务时判断在该全局事务下,“分支 事务记录”表中是否已经有二阶段事务记录,如果有则不执行Try。
具体使用
@LocalTCC
该注解需要添加到上面描述的接口上,表示实现该接口的类被 seata 来管理,seata 根据事务的状态,自动调用我们定义的方法,如果没问题则调用 Commit 方法,否则调用 Rollback 方法。
@LocalTCC
public interface AccountTCCService {}
@TwoPhaseBusinessAction
该注解用在接口的 Try 方法上,该注解的用法如下:
@LocalTCC
public interface AccountTCCService {@TwoPhaseBusinessAction(name = "deduct", commitMethod = "confirm", rollbackMethod = "cancel")void deduct(@BusinessActionContextParameter(paramName = "userId") String userId,@BusinessActionContextParameter(paramName = "money")int money);boolean confirm(BusinessActionContext ctx);boolean cancel(BusinessActionContext ctx);
}
该注解包含这几个属性
- name 为 tcc 方法的 bean 名称,需要全局唯一,一般写方法名即可;
- commitMethod 自然地写 Commit 方法的方法名;
- rollbackMethod 写 Rollback 方法的方法名;
@BusinessActionContextParameter
该注解用来修饰 Try 方法的入参,被修饰的入参可以在 Commit 方法和 Rollback 方法中通过 BusinessActionContext 获取。
最后对接口进行实现即可:
@Service
@Slf4j
public class AccountTCCServiceImpl implements AccountTCCService {@Autowiredprivate AccountMapper accountMapper;@Autowiredprivate AccountFreezeMapper freezeMapper;@Override@Transactionalpublic void deduct(String userId, int money) {// 0.获取事务idString xid = RootContext.getXID();// 1.扣减可用余额accountMapper.deduct(userId, money);// 2.记录冻结金额,事务状态AccountFreeze freeze = new AccountFreeze();freeze.setUserId(userId);freeze.setFreezeMoney(money);freeze.setState(AccountFreeze.State.TRY);freeze.setXid(xid);freezeMapper.insert(freeze);}@Overridepublic boolean confirm(BusinessActionContext ctx) {// 1.获取事务idString xid = ctx.getXid();// 2.根据id删除冻结记录int count = freezeMapper.deleteById(xid);return count == 1;}@Overridepublic boolean cancel(BusinessActionContext ctx) {// 0.查询冻结记录String xid = ctx.getXid();AccountFreeze freeze = freezeMapper.selectById(xid);// 1.恢复可用余额accountMapper.refund(freeze.getUserId(), freeze.getFreezeMoney());// 2.将冻结金额清零,状态改为CANCELfreeze.setFreezeMoney(0);freeze.setState(AccountFreeze.State.CANCEL);int count = freezeMapper.updateById(freeze);return count == 1;}
}
小结
性能:好
模式:AP,存在数据不一致的中间状态
难易程度:复杂,SEATA TC只负责全局事务的提交与回滚指令,具体的回滚处理全靠程序员自己实现(手动写代码)
使用要求:
- 所有服务与数据库必须要自己拥有管理权
- 支持异构数据库,可以使用不同选型实现
相关文章:
Seata之TCC模式解读
目录 基本介绍 起源 概述 案例流程分析 TCC注意事项 空回滚 幂等 悬挂 具体使用 LocalTCC TwoPhaseBusinessAction 小结 基本介绍 起源 关于TCC的概念,最早是由Pat Helland于2007年发表的一篇名为《Life beyond Distributed Transactions:an Apost…...
算法--数据结构
这里写目录标题 本节内容链表与邻接表链表主要思想链表操作初始化在head结点后面插入普通插入删除操作 例子 双链表(双向循环链表)主要思想操作初始化双向插入删除第k个点 邻接表主要思想 栈和队列栈主要思想主要操作 队列主要思想操作 单调栈与单调队列…...
关系型数据库Redis安装与写入数据
文章目录 安装和初步选择数据库创建键值对数据类型 安装和初步 安装 Redis是开源的跨平台非关系型数据库,特点是占用资源低、查询速度快。 首先,在Github上下载最新发布的Redis-xxxx.zip压缩文件,下载之后解压,并将解压后的路径…...
《红蓝攻防对抗实战》十二.内网穿透之利用ICMP协议进行隧道穿透
内网穿透之利用ICMP协议进行隧道穿透 一.前言二.前文推荐三.利用ICMP协议进行隧道穿透1.ICMPsh获取反弹shell2.PingTunnel 搭建隧道 四.本篇总结 一.前言 本文介绍了利用ICMP协议进行隧道穿透的方法。ICMP协议不需要开放端口,可以将TCP/UDP数据封装到ICMP的Ping数据…...
【海德教育】国家开放大学和函授区别有:学校不同、入学门槛不同、学习方式不同、招生对象不同、学习年限不同,具体如下:
一、学校不同。 国家开放大学的招收学校是中央电大和各省市、自治州、市辖区及单设的国家开放大学。函授是成人高考学习方式,成考是普通高等院校举行的、单设的成人高等学校。 二、入学门槛不同。 国家开放大学对入学者的年龄、职业、地区和学习资历等方面都没有太多…...
单片机启动流程
存储器 一个单片机中存在rom和ram,Soc也有rom和ram(ddrx),部分Soc还包含MMU(Memory Manage Unit 内存管理单元)— (用于系统内存管理,比如说虚拟内存空间,内存区间的…...
Linux学习教程(第二章 Linux系统安装)2
第二章 Linux系统安装 四、使用U盘安装Linux系统 前面章节介绍了如何通过虚拟机 VMware 安装 Linux 系统,而实际开发中,我们更多的是要将 Linux 系统直接安装到电脑上。 直接在电脑上安装 Linux 系统的常用方法有 2 种,分别是用光盘安装和用…...
操作系统 | proc文件系统
🌈个人主页:Sarapines Programmer🔥 系列专栏:《操作系统实验室》🔖少年有梦不应止于心动,更要付诸行动。 目录结构 1. 操作系统实验之proc文件系统 1.1 实验目的 1.2 实验内容 1.3 实验步骤 1.4 实验…...
刷题笔记(第五天)
1. 给定一个罗马数字,将其转换成整数。 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 …...
【OpenHarmony内核】Harmony内核互斥性信号量
文章目录 前言一、互斥性信号量是什么?二、互斥性信号量2.1 osSemaphoreNew函数创建并初始化一个信号量对象2.2 osSemaphoreGetName获取信号量对象的名称2.3 osSemaphoreAcquire获取一个信号量令牌2.4 osSemaphoreRelease2.5 osSemaphoreGetCount获取当前信号量令牌的数量2.6 …...
给OFFICE增加一个功能搜索
OFFICE功能几乎是无限的。不论你怎么熟悉,总有出乎意料的功能。前几天我使用EXCEL时,发现一个功能改名了。于是我就想,OFFICE应该增加一个功能搜索: 提供一个搜索输入栏。这个已经有了。输入搜索字串弹出一个面板,附带…...
53基于matlab的Tamura纹理特征提取
基于matlab的Tamura纹理特征提取,包括粗糙度、对比度、方向度、线性度、规则度、粗糙度六种,可替换自己的数据进行特征提取。程序已调通,可直接运行。 53 方向度、线性度、规则度 (xiaohongshu.com)...
C++初阶--类与对象(3)(图解)
文章目录 再谈构造函数初始化列表隐式类型转换explicit关键字 static成员友元类内部类匿名对象拷贝函数时的一些优化 再谈构造函数 在我们之前的构造函数中,编译器会通过构造函数,对对象中各个成员给出一个适合的初始值,但这并不能称之为初始…...
考研分享第1期 | 末9生物跨专业考研北京大学电子信息404分经验分享
全文概览 一、个人信息 二、关于考研的经验分享 三、最后的小Tips 一、个人信息 姓名:Jackson 本科院校:某末流985生物专业 报考院校:北京大学电子信息专业 择校意向:北航计算机、人大高瓴、复旦软院、清华大学深研院、北…...
openGauss学习笔记-120 openGauss 数据库管理-设置密态等值查询-概述及使用gsql操作密态数据库
文章目录 openGauss学习笔记-120 openGauss 数据库管理-设置密态等值查询-概述及使用gsql操作密态数据库120.1 密态等值查询概述120.2 使用gsql操作密态数据库 openGauss学习笔记-120 openGauss 数据库管理-设置密态等值查询-概述及使用gsql操作密态数据库 120.1 密态等值查询…...
软件自动化测试平台
软件测试分类黑盒、白盒、功能、API、接口、压力测试和性能测试, 自动化测试平台是一种用于自动化执行软件测试过程的工具。 一、自动化测试平台-功能性 1. 接口自动化:对接软件的接口进行测试,验证接口的功能和性能。 2. Web 自动化&…...
springMVC 导出Excel ,并提供下载(处理日期格式问题)
目录 1、POI的三个依赖 2、控制层代码 3、业务层代码 4、参考文献: 1、POI的三个依赖 <!-- POI的三个依赖 --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</vers…...
软件工程理论与实践 (吕云翔) 第二章软件过程 课后习题及其答案
软件工程理论与实践 (吕云翔) 第二章课后习题 第二章 软件过程 1.判断题 (1)瀑布模型的最大优点是将软件开发的各个阶段划分得十分清晰。 ( ) (2)螺旋模型是在瀑布模型和增量模型的基础上增加了风险分析活动。( ) …...
HTML跳转锚点
跳转锚点适用于本页面和其他页面的任意标签的跳转以及JavaScript的运行 使用方法即给标签加上独一无二的id属性,再使用a标签跳转 如果是其他页面的标签只需加上其他页面的路径,eg.href"其他页面的路径#zp1" id属性的最好不要使用数字开头 <…...
新能源汽车高压线束是如何快速连接到测试设备上进行电性能测试的
快速连接形成稳定的电测试在新能源行业里面是很常见的测试场景,比如说在新能源汽车行业的电池包、电机、电控制器的电性能测试中会有很多高压线束,需要将这些线束和电池包、电控制器、电机与测试设备快速连接在一起进行相关的EOL/DCR测试。 新能源汽车高…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
