三十九、TCC模式

目录

一、定义

1、需要实现的方法:

2、优点:

3、缺点:

二、原理

1、例子:

2、工作模型图:

3、空回滚和业务悬挂

三、实现TCC模式

1、编写TCC服务接口

2、实现TCC服务接口


一、定义

  • TCC模式是Translucent Transmission Control(半透明传输控制)的简称,是一种网络传输协议。
  • 该协议能够识别网络拥塞,并在拥塞时降低传输速率,以防止丢包和网络拥塞。
  • TCC模式通过在传输过程中监测延迟、丢包和网络拥塞来自动调整传输速率。
  • 该协议适用于多媒体流、实时视频、在线游戏等需要低延迟和高带宽的应用。

1、需要实现的方法:

  • Try:资源的检测和预留;
  • Confirm:完成资源操作业务;要求 Try 成功 Confirm 一定要能成功
  • Cancel:预留资源释放,可以理解为try的反向操作

2、优点:

  • 一阶段完成直接提交事务,释放数据库资源,性能好
  • 相比AT模型,无需生成快照,无需使用全局锁,性能最强
  • 不依赖数据库事务,而是依赖补偿操作,可以用于非事务型数据库

3、缺点:

  • 有代码侵入,需要人为编写tryConfirmCancel接口,太麻烦
  • 软状态,事务是最终一致
  • 需要考虑ConfirmCancel的失败情况,做好幂等处理

二、原理

1、例子:

2、工作模型图:

3、空回滚和业务悬挂

  1. 空回滚

在分布式事务中,一个事务涉及到多个资源,如果其中一个资源在分布式事务提交后因为各种原因(如网络故障、硬件故障等)未提交修改,那么整个分布式事务将无法提交,需要进行回滚操作。但是,如果其他资源已经提交修改,并且无法回滚,则存在空回滚的情况。

空回滚指的是分布式事务中已经提交了修改,但是由于某些原因无法回滚的情况,导致整个事务无法提交,只能回滚,造成了资源的浪费和性能的降低。

  1. 业务悬挂

业务悬挂指的是当一个分布式事务在执行过程中,一个或多个资源长时间被锁定,导致其他分布式事务无法访问该资源,进而产生阻塞和死锁的问题。

例如,在一个分布式事务中,涉及到资源1和资源2。当该事务对资源1进行锁定并执行修改时,在此期间,如果其他事务也需要对资源1进行访问和修改,就需要等待该事务完成;而当该事务需要对资源2进行访问和修改时,如果此时资源2也被其他事务锁定,就会出现阻塞和死锁的情况。

为了避免业务悬挂的问题,分布式事务协调器通常会采用分布式锁机制,通过对资源的锁定和释放来保证分布式事务的并发执行和数据一致性。

三、实现TCC模式

1、编写TCC服务接口

@LocalTCC
public interface AccountTCCService {
    /**
     * Try逻辑,@TwoPhaseBusinessAction中的name属性要与当前方法名一致,用于指定Try逻辑对应的方法
     */
    @TwoPhaseBusinessAction(name = "deduct", commitMethod = "confirm", rollbackMethod = "cancel")
    void deduct(@BusinessActionContextParameter(paramName = "userId") String userId,
                @BusinessActionContextParameter(paramName = "money") int money);

    /**
     * 二阶段confirm确认方法、可以另命名,但要保证与commitMethod一致       *      * @param context 上下文,可以传递try方法的参数      * @return boolean 执行是否成功
     */
    boolean confirm(BusinessActionContext context);

    /**
     * 二阶段回滚方法,要保证与rollbackMethod一致
     */
    boolean cancel(BusinessActionContext context);
}

2、实现TCC服务接口

@Slf4j
@Service
public class AccountTCCServiceImpl implements AccountTCCService {
    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private AccountFreezeMapper accountFreezeMapper;

    @Override
    @Transactional
    public void deduct(String userId, int money) {
        //获取事务id
        String xid = RootContext.getXID();
        //判断freeze中是否有冻结记录,如果有,一定是CANCEL执行过,我要拒绝业务(业务悬挂)
        AccountFreeze oldFreeze = accountFreezeMapper.selectById(userId);
        if (oldFreeze != null) {
            return;
        }
        //扣减可用金额
        accountMapper.deduct(userId, money);
        //记录冻结金额,事务状态
        AccountFreeze freeze = new AccountFreeze();
        freeze.setUserId(userId);
        freeze.setFreezeMoney(money);
        freeze.setState(AccountFreeze.State.TRY);
        freeze.setXid(xid);
        accountFreezeMapper.insert(freeze);
    }

    @Override
    public boolean confirm(BusinessActionContext ctx){
        //查询冻结记录
        String xid = ctx.getXid();
        //根据id删除冻结记录
        int count = accountFreezeMapper.deleteById(xid);
        return count == 1;
    }

    @Override
    public boolean cancel(BusinessActionContext ctx){
        //查询冻结记录
        String xid = ctx.getXid();
        String userId = ctx.getActionContext("userId").toString();
        AccountFreeze freeze = accountFreezeMapper.selectById(xid);
        //空回滚判断
        if (freeze == null) {
            //try未执行,要空回滚
            freeze = new AccountFreeze();
            freeze.setUserId(userId);
            freeze.setFreezeMoney(0);
            freeze.setState(AccountFreeze.State.CANCEL);
            freeze.setXid(xid);
            accountFreezeMapper.insert(freeze);
            return true;
        }
        //幂等判断
        if (freeze.getState() == AccountFreeze.State.CANCEL){
            return true;
        }


        //恢复可用金额
        accountMapper.refund(freeze.getUserId(), freeze.getFreezeMoney());
        //将冻结金额清零,状态改为CANCEl
        freeze.setFreezeMoney(0);
        freeze.setState(AccountFreeze.State.CANCEL);
        int count = accountFreezeMapper.updateById(freeze);
        return count == 1;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/223410.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

获客成本高?低成本获客有哪些途径?

获客成本是一个企业在营销中必须考虑的重要因素之一。它指企业在吸引新客户、推广产品或服务时所需要投入的资金、人力、物力等成本。不仅包括直接成本,如广告费用、促销费用等,还包括间接成本,如市场调研费用、销售人员薪酬等。 获客成本不是…

ELK日志分析

ELK是一套完整的日志集中处理方案,由三个开源软件简称组成: E:ElasticSearch ES 是一个开源的,分布式的存储检索引擎(索引型的非关系型数据库)。存储日志 java代码开发的,基于Lucene结构开发的…

【Java 基础】21 多线程同步与锁

文章目录 1.存在的问题2.使用同步解决问题1) synchronized2) volatile3) 锁 总结 用多线程过程中,有可能出现 多个线程同时处理(获取或修改等)同一个数据,这个时候就 会发生数据不同步的问题, 因此出现了同步和锁来…

用js自定义一个(v-model)vModel双向绑定函数

vue中的v-model是双向绑定的, 我们自己用JavaScript实现一个双向绑定vModel函数。 // element 元素或者#id,.class,div 得是input标签 // data 对象 // 将要绑定property 对象中的key<input class"vmodel"/>function vModel(element, data, property) {if (…

【Proteus】绘制简单的电路图

参考书籍&#xff1a;微机原理与接口技术——基于8086和Proteus仿真&#xff08;第3版&#xff09;&#xff08;作者&#xff1a;顾晖等&#xff09;&#xff0c;p111 1.放置元件 以8086为例&#xff1a; 确保处于元件模式&#xff0c;点击对应的按钮&#xff1a; 在元件库中…

自动生成实体类,mapper类和mapper.xml文件(解放双手,定义好数据库表就不要手写啦)

背景 建的表有四十多个字段&#xff0c;建好了已经很累了&#xff0c;映射成Javabean还要再写一次&#xff01;&#xff01; 吐槽 在建立好了sql表之后&#xff0c;我们已经写了一次建表了&#xff0c;难道还要我们自己再一次手写模Java模型吗&#xff0c;我的表有几十个字段…

数据结构——链式二叉树

前言&#xff1a;哈喽小伙伴们&#xff0c;上篇文章我们讲述了一个特殊的二叉树——使用数组实现的堆的基本知识之后呢&#xff0c;从这篇文章开始&#xff0c;我们就正式进入普通二叉树的介绍啦&#xff0c;二叉树真正的难点——递归&#xff0c;即将来临&#xff0c;小伙伴们…

力扣刷题day2(最长公共前缀,有效括号,删除有序数组中的重复元素)

题目1&#xff1a;14.最长公共前缀 思路和解析&#xff1a; #define _CRT_SECURE_NO_WARNINGS //最长公共前缀 char* longestCommonPrefix(char** strs, int strsSize) {// 如果字符串数组为空&#xff0c;则返回空字符串if (strsSize 0){return "";}// 将第一个…

P7 Linux C三种终止进程的方法

前言 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《C_ChenPi的博客-CSDN博客》✨✨✨ &#x1f525; 推荐专栏2: 《Linux C应用编程&#xff08;概念类&#xff09;_ChenPi的博客-CSDN博客》✨✨✨ &#x1f6f8;推荐专栏3: ​​​​​​《 链表_Chen…

基于深度学习面向中医诊断的舌象图像分割系统

1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义 中医舌诊是通过观察舌的各种特征来了解人体的健康状况&#xff0c;从而对各种疾病做出诊断及病情评估&#xff0c;是传统中国医学应用最广、最有价值的诊法之一。…

632. 最小区间

632. 最小区间 class Solution {public int[] smallestRange(List<List<Integer>> nums) {int size nums.size();Map<Integer, List<Integer>> indices new HashMap<Integer, List<Integer>>();int xMin Integer.MAX_VALUE, xMax Inte…

什么因素会影响葡萄酒陈酿的能力?

糖、酸和酚类与水的比例是葡萄酒陈酿程度的关键决定因素&#xff0c;收获前葡萄中的水分越少&#xff0c;产生的葡萄酒就越有可能具有一定的陈酿潜力。那么葡萄品种、气候和葡萄栽培实践的过程就相当重要了&#xff0c;对陈酿的时间发挥了重要的作用。皮较厚的葡萄品种&#xf…

iOS ------ 调用高德地图SDK

一&#xff0c;导入第三方库 这里使用CocoaPods安装SDK&#xff0c;方法和前面导入第三方库相同 1.打开终端&#xff0c;cd 文件路径 进入到所创建的项目文件中 2.输入pod init为该项目创建Podfile文件 3.编辑 Podfile 文件 Podfile文件内容如下&#xff1a; platform :ios,…

图形遍历效率低?试试 R 树

大家好&#xff0c;我是前端西瓜哥。 今天我们来看看 R 树是什么&#xff1f;以及它为什么能够提高图形的检索速度。 R 树&#xff08;R-tree&#xff09;是一种 空间索引技术&#xff0c;能够是从大量的节点中&#xff0c;快速找到特定范围的元素集合&#xff0c;而不用一个…

Verilog 入门(八)(验证)

文章目录 编写测试验证程序波形产生值序列重复模式 测试验证程序实例从文本文件中读取向量实例&#xff1a;时序检测器 测试验证程序用于测试和验证设计方法的正确性。Verilog 提供强有力的结构来说明测试验证程序。 编写测试验证程序 测试验证程序有三个主要目的&#xff1a;…

JNPF——强大、高效、易学的低代码开发工具

目录 1.什么是低代码 2.什么是JNPF? 3.推荐JNPF的理由 4.小结 你是否为编程世界的各种挑战感到头痛&#xff1f;想要以更高效、简单的方式开发出专业级的项目&#xff1f;JNPF低代码工具正是你苦心寻找的产品&#xff01;它是一款专为稍微懂一点点编程思想的入门级人员设计…

vue elementUI 上传非空验证

<el-form-item label"照片" prop"staffImg"><template v-slot:label><span v-show"!rules.staffImg[0].required"style"color: #ff4949;margin-right: 4px;">*</span><span>照片</span></temp…

【动手学深度学习】(六)权重衰退

文章目录 一、理论知识二、代码实现2.1从零开始实现2.2简洁实现 【相关总结】 主要解决过拟合 一、理论知识 1、使用均方范数作为硬性限制&#xff08;不常用&#xff09; 通过限制参数值的选择范围来控制模型容量 通常不限制偏移b 小的意味着更强的正则项 使用均方范数作为柔…

深入理解TDD(测试驱动开发):提升代码质量的利器

在日常的软件开发工作中&#xff0c;我们常常会遇到这样的问题&#xff1a;如何在繁忙的项目进度中&#xff0c;保证我们的代码质量&#xff1f;如何在不断的迭代更新中&#xff0c;避免引入新的错误&#xff1f;对此&#xff0c;有一种有效的开发方式能帮助我们解决这些问题&a…

CSS中区分行高,行间距

行高&#xff08;line height&#xff09; —文字占有的实际高度 —使用line-height来设置行高 行高类似于我们上学单线本&#xff0c;单线本是一行一行&#xff0c;线与线之间的距离就是行高&#xff0c;控制文字行与行之间的距离&#xff0c; 网页中的文字实际上也是写在一个…
最新文章