SSM 如何使用 TCC 机制实现分布式事务?

news2024/11/26 0:33:58

SSM 如何使用 TCC 机制实现分布式事务?

分布式事务是现代分布式系统中必不可少的一部分,而 TCC 机制(Try-Confirm-Cancel)是一种常用的分布式事务处理方式。在 SSM 框架中,我们可以使用 TCC 机制来管理分布式事务。本文将介绍如何在 SSM 框架中使用 TCC 机制实现分布式事务,并提供相应的代码示例。

在这里插入图片描述

什么是 TCC 机制?

TCC 机制是一种分布式事务处理方式,其核心思想是将一个分布式事务拆分成三个阶段:Try、Confirm 和 Cancel。具体来说,TCC 机制将一个分布式事务拆分成以下三个步骤:

  • Try 阶段:在该阶段中,系统会尝试执行分布式事务。如果所有的业务操作都执行成功,则分布式事务进入 Confirm 阶段。如果任何一个业务操作执行失败,则分布式事务进入 Cancel 阶段。
  • Confirm 阶段:在该阶段中,系统会确认执行所有业务操作。如果所有业务操作都执行成功,则分布式事务提交。如果任何一个业务操作执行失败,则分布式事务回滚。
  • Cancel 阶段:在该阶段中,系统会撤销所有业务操作。如果所有业务操作都成功撤销,则分布式事务回滚完成。如果任何一个业务操作无法撤销,则分布式事务无法回滚。

通过 TCC 机制,我们可以对分布式事务进行更加细粒度的控制,从而降低系统出错的概率。

SSM 中如何使用 TCC 机制实现分布式事务?

在 SSM 框架中,我们可以使用 TCC 机制来管理分布式事务。具体来说,我们可以通过 Spring 的声明式事务管理和 Dubbo 的分布式事务管理来实现 TCC 机制。

Spring 的声明式事务管理

在 Spring 的声明式事务管理中,我们可以使用 @Transactional 注解来实现 TCC 机制。具体来说,我们可以将一个分布式事务拆分成以下三个方法:

  • Try 方法:在该方法中,我们会执行所有的业务操作,并将操作结果保存到一个全局事务上下文对象中。
  • Confirm 方法:在该方法中,我们会确认所有的业务操作。如果所有业务操作都执行成功,则会将全局事务上下文对象中的操作结果提交。如果任何一个业务操作执行失败,则会将全局事务上下文对象中的操作结果回滚。
  • Cancel 方法:在该方法中,我们会撤销所有的业务操作。如果所有业务操作都成功撤销,则会将全局事务上下文对象中的操作结果回滚。如果任何一个业务操作无法撤销,则会将全局事务上下文对象中的操作结果置为“未知”状态。

下面是一个使用 Spring 的声明式事务管理实现 TCC 机制的示例代码:

@Service
public class TccService {
    @Autowired
    private TccDao tccDao;

    @Autowired
    private GlobalTransactionContext globalTransactionContext;

    @Transactional
    public void tryMethod() {
        // 执行业务操作1
        boolean result1 = tccDao.doSomething1();
        // 执行业务操作2
        boolean result2 = tccDao.doSomething2();
        // 将操作结果保存到全局事务上下文对象中
        globalTransactionContext.addResult("result1", result1);
        globalTransactionContext.addResult("result2", result2);
    }

    @Transactional
    public void confirmMethod() {
        // 确认业务操作1
        boolean result1 = globalTransactionContext.getResult("result1");
        if (result1) {
            tccDao.confirmSomething1();
        }
        // 确认业务操作2
        boolean result2 = globalTransactionContext.getResult("result2");
        if (result2) {
            tccDao.confirmSomething2();
        }
        // 提交分布式事务
        globalTransactionContext.commit();
    }

    @Transactional
    public void cancelMethod() {
        // 撤销业务操作1
        boolean result1 = globalTransactionContext.getResult("result1");
        if (result1) {
            tccDao.cancelSomething1();
        }
        // 撤销业务操作2
        boolean result2 = globalTransactionContext.getResult("result2");
        if (result2) {
            tccDao.cancelSomething2();
        }
        // 回滚分布式事务
        globalTransactionContext.rollback();
    }
}

在上面的代码中,我们定义了一个 TccService 类,并使用 @Transactional 注解将 tryMethod()confirmMethod()cancelMethod() 方法标记为需要参与分布式事务的方法。在 tryMethod() 方法中,我们执行了所有的业务操作,并将操作结果保存到全局事务上下文对象中。在 confirmMethod() 方法中,我们通过全局事务上下文对象获取所有的业务操作结果,并根据结果确认或回滚业务操作。在 cancelMethod() 方法中,我们通过全局事务上下文对象获取所有的业务操作结果,并根据结果撤销业务操作。

Dubbo 的分布式事务管理

在 Dubbo 的分布式事务管理中,我们可以使用 @Compensable 注解来实现 TCC 机制。具体来说,我们可以将一个分布式事务拆分成以下三个方法:

  • Try 方法:在该方法中,我们会执行所有的业务操作,并将操作结果保存到一个全局事务上下文对象中。
  • Confirm 方法:在该方法中,我们会确认所有的业务操作。如果所有业务操作都执行成功,则会将全局事务上下文对象中的操作结果提交。如果任何一个业务操作执行失败,则会将全局事务上下文对象中的操作结果回滚。
  • Cancel 方法:在该方法中,我们会撤销所有的业务操作。如果所有业务操作都成功撤销,则会将全局事务上下文对象中的操作结果回滚。如果任何一个业务操作无法撤销,则会将全局事务上下文对象中的操作结果置为“未知”状态。

下面是一个使用 Dubbo 的分布式事务管理实现 TCC 机制的示例代码:

@Service
public class TccService {
    @Autowired
    private TccDao tccDao;

    @Autowired
    private GlobalTransactionContext globalTransactionContext;

    @Compensable(confirmMethod = "confirmMethod", cancelMethod = "cancelMethod")
    public void tryMethod() {
        // 执行业务操作1
        boolean result1 = tccDao.doSomething1();
        // 执行业务操作2
        boolean result2 = tccDao.doSomething2();
        // 将操作结果保存到全局事务上下文对象中
        globalTransactionContext.addResult("result1", result1);
        globalTransactionContext.addResult("result2", result2);
    }

    public void confirmMethod() {
        // 确认业务操作1
        boolean result1 = globalTransactionContext.getResult("result1");
        if (result1) {
            tccDao.confirmSomething1();
        }
        // 确认业务操作2
        boolean result2 = globalTransactionContext.getResult("result2");
        if (result2) {
            tccDao.confirmSomething2();
        }
        // 提交分布式事务
        globalTransactionContext.commit();
    }

    public void cancelMethod() {
        // 撤销业务操作1
        boolean result1 = globalTransactionContext.getResult("result1");
        if (result1) {
            tccDao.cancelSomething1();
        }
        // 撤销业务操作2
        boolean result2 = globalTransactionContext.getResult("result2");
        if (result2) {
            tccDao.cancelSomething2();
        }
        // 回滚分布式事务
        globalTransactionContext.rollback();
    }
}

在上面的代码中,我们定义了一个 TccService 类,并使用 @Compensable 注解将 tryMethod() 方法标记为需要参与分布式事务的方法。在 tryMethod() 方法中,我们执行了所有的业务操作,并将操作结果保存到全局事务上下文对象中。在 confirmMethod() 方法中,我们通过全局事务上下文对象获取所有的业务操作结果,并根据结果确认或回滚业务操作。在 cancelMethod() 方法中,我们通过全局事务上下文对象获取所有的业务操作结果,并根据结果撤销业务操作。

需要注意的是,在 Dubbo 的分布式事务管理中,我们需要使用一个全局事务上下文对象来保存所有的业务操作结果。在上面的示例代码中,我们通过 @Autowired 注解注入了一个 GlobalTransactionContext 对象,用于保存所有的业务操作结果。在实际应用中,我们可以使用 Redis、Zookeeper 等分布式存储系统来实现全局事务上下文对象。

总结

在本文中,我们介绍了如何在 SSM 框架中使用 TCC 机制实现分布式事务。具体来说,我们可以通过 Spring 的声明式事务管理和 Dubbo 的分布式事务管理来实现 TCC 机制。通过 TCC 机制,我们可以对分布式事务进行更加细粒度的控制,从而降低系统出错的概率。在实际应用中,我们需要根据业务场景选择合适的分布式事务处理方式,并根据实际情况进行优化和调整,以提高系统的可靠性和性能。

附:完整代码示例

Dao 层

@Repository
public class TccDao {
    public boolean doSomething1() {
        // 执行业务操作1
        return true;
    }

    public void confirmSomething1() {
        // 确认业务操作1
    }

    public void cancelSomething1() {
        // 撤销业务操作1
    }

    public boolean doSomething2() {
        // 执行业务操作2
        return true;
    }

    public void confirmSomething2() {
        // 确认业务操作2
    }

    public void cancelSomething2() {
        // 撤销业务操作2
    }
}

Service 层

@Service
public class TccService {
    @Autowired
    private TccDao tccDao;

    @Autowired
    private GlobalTransactionContext globalTransactionContext;

    @Transactional
    public void tryMethod() {
        //执行业务操作1
        boolean result1 = tccDao.doSomething1();
        // 执行业务操作2
        boolean result2 = tccDao.doSomething2();
        // 将操作结果保存到全局事务上下文对象中
        globalTransactionContext.addResult("result1", result1);
        globalTransactionContext.addResult("result2", result2);
    }

    @Transactional
    public void confirmMethod() {
        // 确认业务操作1
        boolean result1 = globalTransactionContext.getResult("result1");
        if (result1) {
            tccDao.confirmSomething1();
        }
        // 确认业务操作2
        boolean result2 = globalTransactionContext.getResult("result2");
        if (result2) {
            tccDao.confirmSomething2();
        }
        // 提交分布式事务
        globalTransactionContext.commit();
    }

    @Transactional
    public void cancelMethod() {
        // 撤销业务操作1
        boolean result1 = globalTransactionContext.getResult("result1");
        if (result1) {
            tccDao.cancelSomething1();
        }
        // 撤销业务操作2
        boolean result2 = globalTransactionContext.getResult("result2");
        if (result2) {
            tccDao.cancelSomething2();
        }
        // 回滚分布式事务        globalTransactionContext.rollback();
    }
}

全局事务上下文对象

@Component
public class GlobalTransactionContext {
    private Map<String, Object> results = new HashMap<>();

    public void addResult(String key, Object value) {
        results.put(key, value);
    }

    public Object getResult(String key) {
        return results.get(key);
    }

    public void commit() {
        // 提交分布式事务
    }

    public void rollback() {
        // 回滚分布式事务
    }
}

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

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

相关文章

RabbitMQ系列-概念及安装

1. 消息队列 消息队列是指利用队列这种数据结构进行消息发送、缓存、接收&#xff0c;使得进程间能相互通信&#xff0c;是点对点的通信 而消息代理是对消息队列的扩展&#xff0c;支持对消息的路由&#xff0c;是发布-订阅模式的通信&#xff0c;消息的发送者并不清楚消息的…

Spring源码解析

Idea导入Spring源码 下载 下载gradle 因为Spring源码里没有使用Maven依赖&#xff0c;而是使用gradle依赖&#xff0c;所以我们需要在本地下载安装并配置gradle环境。注意&#xff0c;这里下载安装的gradle版本应与Spring源码中的gradle版本对应。这里推荐下载我的&#xff…

Linux网络服务:部署YUM仓库与NFS服务

目录 一、理论 1.部署YUM仓库服务 2.NFS共享存储服务 二、实验 1.通过httpd服务建立yum仓库 2.通过vsftpd服务建立yum仓库 3.搭建NFS实现2台或3台服务器共享一个目录 一、理论 1.部署YUM仓库服务 (1) YUM简介 YUM的前身是YUP&#xff0c;借助于YUM软件仓库&#xff0c…

关于原型链

1-__proto__([[Prototype]])和prototype 每个对象都有一个隐式原型&#xff0c;这个隐式原型可以通过 obj.__proto__ Object.getPrototypeOf(obj)这两种方式获取&#xff1b; 我们都知道对象是通过构造函数构造的&#xff0c;new关键字构造的&#xff0c; 构造函数上有一个显…

如何在华为OD机试中获得满分?Java实现【最佳对手】一文详解!

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: Java华为OD机试真题(2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述4. Java算法源码5. 测试6.解题思路1. 题目描述 游戏里面,队伍通过匹配…

native层函数没有导出时,如何获得相应函数地址?

前言 每次App重新运行后native函数加载的绝对地址是会变化的&#xff0c;唯一不变的是函数相对于基地址的偏移&#xff0c;因此我们可以在获取模块的基地址后加上固定的偏移地址获取相应函数的地址&#xff0c;Frida中也正好提供了这种方式&#xff1a;先通过Module.findBaseA…

SQL教程1

SQL 是用于访问和处理数据库的标准的计算机语言。 在本教程中&#xff0c;您将学到如何使用 SQL 访问和处理数据系统中的数据&#xff0c;这类数据库包括&#xff1a;MySQL、SQL Server、Access、Oracle、Sybase、DB2 等等。 SQL 简介 SQL (Structured Query Language:结构化…

OSPF协议

OSPF&#xff1a;开放式最短路径优先协议 无类别IGP协议&#xff1b;链路状态型&#xff1b;基于LSA收敛&#xff0c;故更新量较大&#xff0c;为在中大型网络正常工作&#xff0c;需要进行结构化的部署 --- 区域划分、ip地址规划 组播更新 --- 224.0.0.5 224.0.0.6 支持等开销…

shell变量的使用 rhce(25)

目录 1.总结变量的类型及含义&#xff1f; 2.实现课堂案例计算长方形面积&#xff1f;&#xff08;6种方式&#xff09; 3.定义变量urlhttps://blog.csdn.net/weixin_45029822/article/details/103568815&#xff08;通过多种方法实现&#xff09; &#xff08;1&#xff0…

Redis的数据过期策略

数据淘汰策略-使用建议 1.优先使用allkeys-lru策略。充分利用LRU算法的优势&#xff0c;把最近最常访问的数据留在缓存中。如果业务有明显的冷热数据区分&#xff0c;建议使用。 2.如果业务中数据访问频率差别不大&#xff0c;没有明显冷热数据区分&#xff0c;建议使用allkeys…

【AUTOSAR】 AUTOSAR整体开发流程(六)---- ISOLAR与Simuink

ISOLAR与Simuink交互 8.1 AutoSar的几种开发流程 8.2 Simulink 到ISOLAR Simulink生成SWC arxml SWC arxml放到ISOLAR文件夹 F5即可显示 8.3 ISOLAR到Simulink 1、Matlab的几个命令 1&#xff09;importer Call the constructor arxml.importer to create an importer obj…

Nomad 会替代 Kubernetes 吗?对比一下,两者如何选择?

概 述 根据市场状况&#xff0c;Kubernetes&#xff08;又称“K8s”&#xff09;已经成为容器编排之王&#xff0c;超越了Docker Swarm和Mesos等竞争对手。但是&#xff0c;在K8s&#xff08;2014&#xff09;出现的同时&#xff0c;还有另一个编排项目HashiCorp的Nomad&…

同城跑腿系统源码,点对点配送,帮你省时省力

随着互联网的发展&#xff0c;越来越多的人开始依赖网络来解决生活中的各种问题。而同城跑腿系统就是其中一个受欢迎的解决方案。 ​同城跑腿系统是指一种基于互联网的服务&#xff0c;通过在线平台将用户和服务提供者连接起来&#xff0c;以便用户可以轻松地安排他们的日常任务…

Selenium Grid- 让自动化分布式执行变得可能

什么是 Selenium Grid&#xff1f; Selenium Grid 是 Selenium 的三大组件之一&#xff0c;允许用户同时在不同的机器和系统上测试不同浏览器。 也就是说 Selenium Grid 支持分布式的测试执行。它可以让你的测试用例在一个分布式的执行环境中运行。 由上图可见&#xff0c;测试…

Python之并发编程二多进程理论

一、什么是进程 进程&#xff1a;正在进行的一个过程或者说一个任务。而负责执行任务则是cpu。 二、进程与程序的区别 程序仅仅只是一堆代码而已&#xff0c;而进程指的是程序的运行过程。 三、并发与并行 无论是并行还是并发&#xff0c;在用户看来都是’同时’运行的&am…

从实际案例聊聊Java应用的GC优化

概 述 当Java程序的性能无法达到预期目标时&#xff0c;开发人员通常需要借助GC优化来进一步提高性能。然而&#xff0c;GC算法复杂&#xff0c;影响GC性能的参数众多&#xff0c;且参数调整又依赖于应用各自的特点&#xff0c;这些因素大大增加了GC优化的难度。不过&#xf…

GitLab 目录遍历漏洞复现(CVE-2023-2825)

0x01 产品简介 Gitlab是目前被广泛使用的基于git的开源代码管理平台, 基于Ruby on Rails构建, 主要针对软件开发过程中产生的代码和文档进行管理&#xff0c;同时可以搭建Web服务。 0x02 漏洞概述 GitLab 存在目录遍历漏洞&#xff0c;当嵌套在至少五个组中的公共项目中存在附…

demlia机器人建模与装配

1 可以用catia中的模型或其他三维建模软件中的模型转化为step格式即可 2 在demlia中打开 3 打开单个零件保存为cgr格式 对机械臂所有零件都做同样的转化 4 新建装配设计&#xff0c;并导入带有坐标的零件 将转化后的零件都选中导入即是装配好的 5 将模式修改为device buildin…

mysql超全语法大全

mysql安装教程 一、登录&#xff08;使用可视化工具&#xff0c;可忽略&#xff09; 打开命令行工具&#xff0c;输入以下命令&#xff0c;根据提示输入 root 用户的密码。 mysql -u root -p mysql -u root -p -D 数据库名二、创建数据库 显示数据库&#xff1a;SHOW DATAB…

Shell脚本攻略:条件语句if、case

目录 一、理论 1.条件测试 2.if语句 3.case语句 二、实验 1.实验一 2.实验二 3.实验三 4.实验四 5.实验五 6.实验六 7.实验七 一、理论 1.条件测试 &#xff08;1&#xff09;三种测试方法 ① test命令测试 ② [ ]测试&#xff08;注意前后需要有空格&…