三十九、TCC模式

news2025/1/22 17:52:16

目录

一、定义

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.coloradmin.cn/o/1290080.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三焦不通,百病丛生?三焦指的到底是什么?

本 期 导 读 今天来讲一讲,看起来比较古怪的腑——三焦。 三焦的名字虽出于《内经》,但对它的描述却不像其他十一脏腑那么具体,留下了极大的解说空间。 三焦真的不可捉摸吗?当然不是。本文就带你揭开三焦的那层似有还无的面纱…

SQL手工注入漏洞测试(Access数据库)-墨者

———靶场专栏——— 声明:文章由作者weoptions学习或练习过程中的步骤及思路,非正式答案,仅供学习和参考。 靶场背景: 来源: 墨者学院 简介: 安全工程师"墨者"最近在练习SQL手工注入漏洞&#…

YOLOv8改进 | TripletAttention三重注意力机制(附代码+机制原理+添加教程)

一、本文介绍 本文给大家带来的改进是Triplet Attention三重注意力机制。这个机制,它通过三个不同的视角来分析输入的数据,就好比三个人从不同的角度来观察同一幅画,然后共同决定哪些部分最值得注意。三重注意力机制的主要思想是在网络中引入…

社区生鲜店铺线上管理平台,提升店铺运营管理效率的秘密武器

智慧零售是一种基于现代技术的零售模式,通过人工智能、大数据分析和物联网等先进技术的运用,对商品销售、用户需求和市场趋势进行深度分析和预测,从而实现精细化管理和个性化服务。智慧零售不仅可以优化商品的库存管理和运营效率,…

java单人聊天

服务端 package 单人聊天;import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import…

【源码解析】聊聊阻塞队列之BlockingArrayQueue

阻塞队列 阻塞队列:顾名思义 首先它是一个队列,而一个阻塞队列在数据结构中所起的作用大致如下入所示。 当阻塞队列是空时,从队列中获取元素的操作将会被阻塞。当阻塞队列时满的时,往队列里添加元素的操作将会被阻塞。 试图从空的…

【沐风老师】3DMAX切片工具插件安装使用方法详解

3DMAX切片工具安装使用方法 3DMAX切片工具,该工具沿世界坐标轴以规则的间隔对对象进行切片处理。例如,对于快速均匀细分复杂网格、顶点绘制或应用“弯曲”修改器非常有用。 【适用版本】 3dMax2016 - 2023(不仅限于此范围) 【安装…

Spring Cloud Stream 4.0.4 rabbitmq 发送消息多function

使用 idea 创建 Springboot 项目 添加 Spring cloud stream 和 rabbitmq 依赖 pom文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchem…

多人聊天室

1.创建服务面板 package yiduiy;import java.awt.BorderLayout; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Has…

国内AI大模型已近80个,哪个最有前途?

目前&#xff0c;国内已经推出了近80个人工智能大模型&#xff0c;这些大模型各有优势&#xff0c;难以直接判断哪个最有前途。然而&#xff0c;以下几个大模型值得关注&#xff1a; 1、华为云盘古大模型&#xff1a;盘古大模型聚焦于为行业服务&#xff0c;包括自然语言、视觉…

基于Vue.js的厦门旅游电子商务预订系统的设计和实现

项目编号&#xff1a; S 030 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S030&#xff0c;文末获取源码。} 项目编号&#xff1a;S030&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 景点类型模块2.2 景点档案模块2.3 酒…

吴恩达《机器学习》11-1-11-2:首先要做什么、误差分析

一、首先要做什么 选择特征向量的关键决策 以垃圾邮件分类器算法为例&#xff0c;首先需要决定如何选择和表达特征向量 &#x1d465;。视频提到的一个示例是构建一个由 100 个最常出现在垃圾邮件中的词构成的列表&#xff0c;根据这些词是否在邮件中出现来创建特征向量&…

Windows磁盘管理中硬盘无法初始化怎么办?

硬盘未出现在“此电脑”选项下的情况并不少见&#xff0c;当您打开磁盘管理&#xff0c;它要么显示为磁盘未知&#xff0c;要么显示为未分配的空间&#xff0c;或者只是不显示磁盘容量。为了访问您的硬盘并充分利用它&#xff0c;您需要对其进行初始化。不幸的是&#xff0c;您…

CTF 6

信息收集 话不多说&#xff0c;nmap进行信息收集&#xff01; 存活主机探测 服务版本探测 端口探测 漏洞脚本探测 UDP端口探测 渗透测试 先看看网站的首页&#xff0c;发现了几个用户&#xff1a; 直接先保存下来吧&#xff0c;以防后面会用到。 SQL注入 看到一个read mor…

行业研究:2023年中国游戏陪玩行业市场现状分析

近年来随着我国游戏行业的不断发展&#xff0c;我国游戏用户规模也是随着稳步上升&#xff0c;给游戏陪玩行业带来了稳定的用户基础。在用户规模增长的同时&#xff0c;随着经济、文化的快速发展&#xff0c;我国娱乐技能社交也随之逐渐兴起。而作为我国娱乐技能社交比重较大的…

01-Redis核心数据结构与高性能原理

一、Redis的单线程和高性能 1. Redis是单线程吗&#xff1f; Redis的单线程主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的&#xff08;说白了也就是执行命令的时候是由一个线程来完成的&#xff09;&#xff0c;这也是 Redis 对外提供键值存储服务的主要流程。…

Jave内存模型 与 CPU硬件架构 的交互图

JMM里所讲的主内存、工作内存与Java内存区域中的Java堆、栈、方法区等并不是同一个层次的对内存的划分&#xff0c;这两者基本上是没有任何关系的。 如果两者一定要勉强对应起来&#xff0c;那么从变量、主内存、工作内存的定义来看&#xff0c;主内存主要对应于Java堆中的对象…

JAVAEE初阶相关内容第十九弹--网络原理之TCP_IP【续集2】

写在前 上一篇博客主要介绍的是关于网络层协议-IP协议的重点介绍。需要掌握关于IP协议的协议头格式&#xff0c;关于IPV4分配不够的解决办法。地址管理与路由选择。 点击跳转上一篇博客 本篇博客将继续学习关于计网中协议的内容。 本篇博客主要介绍关于数据链路层的重点协议-以…

深信服行为管理AC设置禁止用户使用向日葵等远程软件

需求&#xff1a;在特定的时间内禁止内外网用户使用向日葵、todesk等远程软件&#xff1b;只禁止使用专业的远程软件&#xff0c;内网的ssh、telnet、RDP需要正常放行 AC版本&#xff1a;AC13.0.62.001 Build20221107 通过访问权限策略来控制 1、行为管理→访问权限策略→新…

封装校验-----Vue3+ts项目

登录校验页面 <script setup lang"ts"> import { ref } from vue import { mobileRules, passwordRules } from /utils/rules const mobile ref() const password ref() </script><!-- 表单 --><van-form autocomplete"off">&l…