分布式事务解决方案——TCC
TCC是Try、Confirm、Cancel三个词语的缩写,TCC要求每个分支事务实现三个操作:预处理Try、确认Confirm、撤销Cancel。
1、Try 阶段是做业务检查(一致性)及资源预留(隔离),此阶段仅是一个初步操作,它和后续的Confirm一起才能真正构成一个完整的业务逻辑。
2、Confirm 阶段是做确认提交,Try阶段所有分支事务执行成功后开始执行Confirm。通常情况下,TCC认为Confirm阶段是不会出错的,若Confirm阶段真的出错了,则重试或人工处理。
3、Cancel 阶段是在业务执行错误需要回滚的状态下执行分支事务的业务取消,预留资源释放。通常情况下,TCC认为Cancel阶段也是一定成功的,若Cancel阶段真的出错了,则重试或人工处理。
TM(事务管理器)首先发起所有的分支事务的try操作,任何一个分支事务的try操作执行失败,TM将会发起所有分支事务的Cancel操作;若try操作全部成功,TM将会发起所有分支事务的Confirm操作,其中Confirm/Cancel操作若执行失败,TM会进行重试。
所有try都成功

有一个try失败

特别提醒
所有分支事务的try阶段执行成功,则会执行confirm阶段。TCC认为confirm阶段一定会执行成功,如果confirm执行失败,则会重试或者人工处理错误。
任何一个分支事务的try阶段执行失败,则会执行cancel阶段。TCC认为cancel阶段一定会执行成功,如果cancel执行失败,则会重试或者人工处理错误。
TCC需要注意三种异常处理分别是:空回滚、幂等、悬挂。
空回滚

事务管理器调用服务的try操作,可能会出现因为丢包而导致的网络超时,导致应用的try阶段没执行,事务管理器认为执行try超时,会触发cancel操作。这就导致cancel比try先执行。
悬挂

1、事务协调器在调用 TCC 服务的一阶段 Try 操作时,可能会出现因网络拥堵而导致的超时。
2、此时事务管理器会触发二阶段回滚,调用 TCC 服务的 Cancel 操作,Cancel 执行正常。
3、在此之后,拥堵在网络上的一阶段 Try 数据包被 TCC 服务收到,出现了二阶段 Cancel 请求比一阶段 Try 请求先执行的情况。
4、此 TCC 服务在执行晚到的 Try 之后,将永远不会再收到二阶段的 Confirm 或者 Cancel ,造成 TCC 服务悬挂。
幂等
try、confirm、cancel都会被重复调用,需要做幂等处理。
处理空回滚、悬挂、幂等
可以使用日志表,来解决 空回滚、悬挂、幂等。
新建3张表
try阶段日志表local_try_log | |
字段 | 注释 |
tx_no | 全局事务id |
create_time | 创建时间 |
confirm阶段日志表local_confirm_log | |
字段 | 注释 |
tx_no | 全局事务id |
create_time | 创建时间 |
cancel阶段日志表local_cancel_log | |
字段 | 注释 |
tx_no | 全局事务id |
create_time | 创建时间 |
例子
从银行1转账10元给银行2,使用TCC方案
方案1
银行1
try:幂等校验,查找try日志(全局事务id是主键)悬挂处理,查找confirm、cancel日志(全局事务id是主键)检查余额是否够10元锁定10元插入try日志(全局事务id是主键)
confirm:幂等校验,查找confirm日志(全局事务id是主键)扣减10元删除锁定10元插入confirm日志(全局事务id是主键)
cancel:cancel幂等校验,查找cancel日志(全局事务id是主键)空回滚处理,查找try日志(全局事务id是主键)增加余额10元(回滚)删除锁定10元插入cancel日志(全局事务id是主键)银行2
try:幂等校验,查找try日志(全局事务id是主键)悬挂处理,查找confirm、cancel日志(全局事务id是主键)插入待激活10元插入try日志(全局事务id是主键)
confirm:幂等校验,查找confirm日志(全局事务id是主键)正式增加30元删除待激活10元插入confirm日志(全局事务id是主键)
cancel:空由于业务很简单,上面的流程还可以取消锁定,解锁的操作,直接在银行1的try中扣减10元,流程如下。
方案2
银行1
try:幂等校验,查找try日志(全局事务id是主键)悬挂处理,查找confirm、cancel日志(全局事务id是主键)检查余额是否够10元扣减10元插入try日志(全局事务id是主键)
confirm:空
cancel:cancel幂等校验,查找cancel日志(全局事务id是主键)空回滚处理,查找try日志(全局事务id是主键)增加余额10元(回滚)插入cancel日志(全局事务id是主键)银行2
try:空
confirm:幂等校验,查找confirm日志(全局事务id是主键)正式增加30元插入confirm日志(全局事务id是主键)
cancel:空Hmily实现方案2的代码
服务1
@Service
@Slf4j
public class Bank1ServiceImpl implements Bank1Service {@AutowiredAccountInfoDao accountInfoDao;@AutowiredHmilyLogDao hmilyLogDao;@AutowiredBank2Client bank2Client;@Override@Transactional(rollbackFor = Exception.class)@Hmily(confirmMethod = "confirm", cancelMethod = "cancel")public void updateAccountBalance(String msg, Double amount) {// 全局事务idString transId = HmilyTransactionContextLocal.getInstance().get().getTransId();log.info("bank1 try 开始,transId={}", transId);// 幂等判断int existTry = hmilyLogDao.isExistTry(transId);// 通故全局事务id查找到try日志,表明已经只执行过tryif (existTry > 0) {log.info("已经执行过try,无需重复执行try,transId={}", transId);return;}// 悬挂处理int existConfirm = hmilyLogDao.isExistConfirm(transId);int existCancel = hmilyLogDao.isExistCancel(transId);// 通故全局事务id查找到confirm、cancel日志,表明已经只执行过confirm、cancelif (existConfirm > 0 || existCancel > 0) {log.info("confirm,cancel有一个已经执行过,try不能再次执行,transId={}", transId);return;}// 制造空回滚if (StringUtils.equals("制造空回滚", msg)) {throw new RuntimeException("try方法没修改数据库就抛出异常,cancel方法会执行,形成空回滚,transId=" + transId);}// blank1减金额accountInfoDao.subtractAccountBalance("1", amount);// 添加try日志记录,try日志和扣减余额在同一个本地事务中,要么都成功,要么都失败// 日志的组件id必须是全局事务id,如果同一个事物重复调用try,到这一步会报主键重复hmilyLogDao.addTry(transId);// 远程调用Boolean result = bank2Client.transfer(msg, amount);if (!result) {throw new RuntimeException("调用bank2失败");}// bank1调用bank2成功后,发生异常,模拟回滚if (StringUtils.equals("bank1调用bank2成功后,发生异常,模拟回滚", msg)) {throw new RuntimeException("bank1调用bank2成功后,发生异常,模拟回滚,transId=" + transId);}}public void confirm(String accountNo, Double amount) {String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();log.info("bank1 confirm 开始执行,transId={}", transId);}@Transactional(rollbackFor = Exception.class)public void cancel(String msg, Double amount) {// 全局事务idString transId = HmilyTransactionContextLocal.getInstance().get().getTransId();log.info("bank1 cancel 开始执行,transId={}", transId);// 幂等判断int existCancel = hmilyLogDao.isExistCancel(transId);if (existCancel > 0) {log.info("cancel已经执行过,无需重复执行,transId={}", transId);return;}// 处理空回滚int existTry = hmilyLogDao.isExistTry(transId);if (existTry == 0) {log.info("try未执行过,不能执行cancel,transId={}", transId);return;}// bank1回滚,加钱accountInfoDao.addAccountBalance(msg, amount);// 添加日志hmilyLogDao.addCancel(transId);}}
@Service
@Slf4j
public class Bank2ServiceImpl implements Bank2Service {@AutowiredAccountInfoDao accountInfoDao;@AutowiredHmilyLogDao hmilyLogDao;@Override@Hmily(confirmMethod = "confirm", cancelMethod = "cancel")public void updateAccountBalance(String msg, Double amount) {String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();log.info("bank2 try 开始执行,transId:{}",transId);}@Transactional(rollbackFor = Exception.class)public void confirm(String msg, Double amount) {// 全局事务idString transId = HmilyTransactionContextLocal.getInstance().get().getTransId();log.info("bank2 confirm 开始执行,transId:{}",transId);int existConfirm = hmilyLogDao.isExistConfirm(transId);if (existConfirm > 0) {log.info("bank2 confirm 已经执行过,无需再次执行,transId", transId);return;}// bank2加钱accountInfoDao.addAccountBalance("2", amount);// 添加confirm日志hmilyLogDao.addConfirm(transId);// bank2 confirm,抛出异常,会重试if (StringUtils.equals("confirm抛出异常会重试", msg)) {throw new RuntimeException("confirm抛出异常会重试,transId=" + transId);}}public void cancel(String msg, Double amount) {String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();log.info("bank2 cancel 开始执行,transId:{}",transId);}}
相关文章:
分布式事务解决方案——TCC
TCC是Try、Confirm、Cancel三个词语的缩写,TCC要求每个分支事务实现三个操作:预处理Try、确认Confirm、撤销Cancel。1、Try 阶段是做业务检查(一致性)及资源预留(隔离),此阶段仅是一个初步操作,它和后续的Confirm一起才能真正构成…...
ITSS认证分为几个级别,哪个级别最高
一、什么是ITSS ITSS( 信息技术服务标准,简称ITSS)是国内第一套成体系和综合配套的信息技术服务标准库,全面规范了IT服务产品及其组成要素,用于指导实施标准化和可信赖的IT服务。 ITSS是在工业和信息化部、国家标准化管理委员会的联合指导下…...
ZigBee案例笔记 - USART
文章目录1.串行通信接口简述2.串行通信接口寄存器U0CSR (0x86) -USART 0 控制和状态U0UCR (0xC4)–USART 0 UART 控制U0GCR (0xC5)–USART 0 通用控制U0BUF (0xC1) – USART 0 接收/传送数据缓存U0BAUD (0xC2) – USART 0 波特率控制3.设置串行通信接口比特率控制寄存器4.外设I…...
java | 基于Redis的分布式锁实现①
前言 首先,为了确保分布式锁可用,我们至少要确保锁的实现同时满足以下四个条件: 互斥性。在任意时刻,只有一个客户端能持有锁。不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户…...
十六、基于FPGA的CRC校验设计实现
1,CRC校验循环冗余校验(Cyclic Redundancy Check, CRC)是一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术,主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除法及余数的…...
2022爱分析 · DataOps厂商全景报告 | 爱分析报告
报告编委 李喆 爱分析合伙人&首席分析师 廖耘加 爱分析分析师 目录 1. 研究范围定义 2. 市场洞察 3. 厂商全景地图 4. 市场分析与厂商评估 5. 入选厂商列表 1. 研究范围定义 研究范围 在后疫情时代,以数据分析为代表的数据消费场景日益丰富&…...
京东前端react面试题及答案
useEffect 与 useLayoutEffect 的区别 (1)共同点 运用效果: useEffect 与 useLayoutEffect 两者都是用于处理副作用,这些副作用包括改变 DOM、设置订阅、操作定时器等。在函数组件内部操作副作用是不被允许的,所以需…...
TongWeb8数据源相关问题
问题一:数据源连接不足当TongWeb数据源连接用完时,除了监控中看到连接占用高以外,日志中会有如下提示信息。2023-02-14 10:24:43 [WARN] - com.tongweb.web.jdbc.pool.PoolExhaustedException: [TW-0.0.0.0-8088-3] Timeout: Pool empty. Una…...
关于最近大热的AI,你怎么看?
AI人工智能,相信大家都不陌生,也都接触过不少。但是最近小编在网上冲浪的时候发现各大媒体又掀起了一阵AI热潮,AI不是很常见了吗?是又有什么新的发展吗? 带着强烈的好奇心,我在地铁上读完了一篇关于Chatgp…...
25.架构和软件产品线
文章目录25 Architecture and Software Product Lines架构和软件产品线25.1 An Example of Product Line Variability 产品线可变性的一个例子25.2 What Makes a Software Product Line Work? 软件产品线的工作原理是什么?25.3 Product Line Scope 产品线范围25.4 …...
Seata-server 源码学习(一)
Seata源码学习引入 学习了Seata的应用以后,我们从这开始要开始分析Seata的源码相关内容 源码下载 官方地址:https://seata.io/zh-cn/blog/download.html 通过idea打开seata-1.4.2版本的源码 回顾AT模式 其实在之前的应用课程中,我们已经用…...
2023新华为OD机试题 - 斗地主(JavaScript)
斗地主 题目 斗地主起源于湖北十堰房县, 据传是一位叫吴修全的年轻人根据当地流行的扑克玩法“跑得快”改编的, 如今已风靡整个中国,并流行于互联网上 牌型: 单顺,又称顺子,最少5张牌,最多12张牌(3...A),不能有2, 也不能有大小王,不计花色 例如:3-4-5-7-8,7-8-9-1…...
素数相关(结合回文数,合数)线性筛素数(欧拉筛法)Euler【算法模板笔记】
一、朴素筛法(埃拉托斯特尼筛法)Eratosthenes 筛法(埃拉托斯特尼筛法,简称埃氏筛法)时间复杂度是O(nloglogn)不常用,被欧拉筛代替,略二、线性筛素数(欧拉筛法)简介线性筛…...
1.7配置OSPF手动汇总
实验7:配置OSPF手动汇总 实验目的实现OSPF路由汇总的配置阐明OSPF引入的外部路由时进行路由汇总的方法实验拓扑配置OSPF手动汇总实验拓扑如图1-17所示。 图1-17 配置OSPF手动汇总 实验步骤配置IP地址,配置OSPF(和实验6一致,此处略)在…...
多线程下载工具axel的安装和使用
多线程下载工具axel的安装和使用 Axel是一个轻量级下载程序,它和其他加速器一样,对同一个文件建立多个连接,每个连接下载单独的文件片段以更快地完成下载。 Axel 支持 HTTP、HTTPS、FTP 和 FTPS 协议。它也可以使用多个镜像站点下载单个文件…...
大数据专业职业前景如何
大数据专业毕业生未来的岗位选择空间比较大,有三大类岗位可选择分别是大数据开发岗位、大数据分析岗位和大数据运维岗位,在不同的行业和技术体系结构下这些岗位也包含很多细分的岗位。 大数据开发岗位分为平台研发岗位和行业场景开发岗位两大类…...
拉格朗日乘数法在原材料选择问题上的具体应用
问题需求: 输入待制作的材料:(材料长,材料数量) 分别为(5401,124)、(200,135)、(1350,45), 输入原材料长度最大值6500,最小值3500&…...
零信任-腾讯零信任iOA介绍(4)
腾讯零信任介绍 腾讯零信任是一种信息安全架构,旨在通过限制对计算设备、数据和应用程序的访问来保护敏感信息。腾讯零信任的主要思想是,任何计算设备、数据或应用程序都不应被自动信任,并需要经过授权后才能访问敏感信息。 腾讯零信任的…...
标准的maven依赖包应该包含哪些东西?
背景在阅读源码的时候,发现有一些maven依赖包里面没有包含pom文件,一些maven依赖包包含,而且除此之外还有一些细微的差异。今天就来聊一下关于一个标准的依赖包应该是什么样子的。一个标准的Maven依赖包通常包含以下文件:Java类文…...
网络安全-Nmap
网络安全-Nmap Nmap-号称诸神之眼 这个呢就是用来扫描网络端口的 Namp的工作原理很像一个雷达 做任何攻击之前,得先知道怎么去找破绽,而不是钢铁洪流,那个是不叫渗透了,叫硬钢。 咋用呢? 很简单 直接 nmap 后面跟网址…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
32单片机——基本定时器
STM32F103有众多的定时器,其中包括2个基本定时器(TIM6和TIM7)、4个通用定时器(TIM2~TIM5)、2个高级控制定时器(TIM1和TIM8),这些定时器彼此完全独立,不共享任何资源 1、定…...
电脑桌面太单调,用Python写一个桌面小宠物应用。
下面是一个使用Python创建的简单桌面小宠物应用。这个小宠物会在桌面上游荡,可以响应鼠标点击,并且有简单的动画效果。 import tkinter as tk import random import time from PIL import Image, ImageTk import os import sysclass DesktopPet:def __i…...
基于stm32F10x 系列微控制器的智能电子琴(附完整项目源码、详细接线及讲解视频)
注:文章末尾网盘链接中自取成品使用演示视频、项目源码、项目文档 所用硬件:STM32F103C8T6、无源蜂鸣器、44矩阵键盘、flash存储模块、OLED显示屏、RGB三色灯、面包板、杜邦线、usb转ttl串口 stm32f103c8t6 面包板 …...
EasyRTC音视频实时通话功能在WebRTC与智能硬件整合中的应用与优势
一、WebRTC与智能硬件整合趋势 随着物联网和实时通信需求的爆发式增长,WebRTC作为开源实时通信技术,为浏览器与移动应用提供免插件的音视频通信能力,在智能硬件领域的融合应用已成必然趋势。智能硬件不再局限于单一功能,对实时…...
