微服务13-Seata的四种分布式事务模式

news2025/5/11 19:53:23

文章目录

  • XA模式
    • 实现XA模式
  • AT模式
    • AT模式的脏写问题(对同数据并发写的问题)
    • 其他事务不获取全局锁的一个情况(AT模式写隔离的实现)
    • 实现AT模式
  • TCC模式
    • TCC实现
    • 我们怎么样去判断是否空回滚和业务悬挂?
    • 业务分析
  • Saga模式
    • 总结

XA模式

XA模式分为两种情况
提交成功:
在这里插入图片描述

提交失败:

在这里插入图片描述

具有强一致性seata相当于是在RM上做了一层封装;

在这里插入图片描述

XA模式
优点
1.事务的强一致性,只要有失败的,TC事务协调者就会发送信息让RM回滚——>满足ACID原则
2.没有代码侵入,常用数据库都支持
缺点
1.第一阶段就要锁定数据库资源,但是却不提交,从而导致数据库所占用的资源不能释放(占数据库锁),性能较差
2.依赖关系型数据库实现事务

实现XA模式

步骤:

1.在yaml文件中开启XA代理模式

2.添加@GlobalTransactional注解开启全局事务

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

AT模式

在这里插入图片描述
利用快照来保证事务的一致性,来进行数据回滚;

在这里插入图片描述

AT模式是一种最终一致的模式:因为RM资源管理器执行sql后会直接提交,那么此时如果是数据不一致的情况下,那么说明肯定是软一致,但是在阶段二时,AT模式RM资源管理器会利用快照进行数据回滚,从而保证最终一致;
AT模式直接提交,有利于提高效率

在这里插入图片描述

AT模式的脏写问题(对同数据并发写的问题)

脏写问题:造成数据空转现象

什么是脏写:

简而言之,就是两个事务并发执行,修改同一条数据,我第一个事务修改并且提交之后,释放DB锁资源,第二个事务想要进行回滚,那么就会导致脏写——>前一个事务修改无效

在这里插入图片描述
解决:对事务2造成数据空转现象进行处理

1.事务1先获取DB锁,并且保存快照
——>2.然后执行业务sql,我们在提交事务前获取全局锁(防止一提交事务,释放DB锁后,其他事务立马插入获取DB锁更改sql)
——>3.此时全局锁会记录操作当前数据的事务,让该事务持有全局锁,然后提交事务释放DB锁
——>4.此时其他事务可以争夺DB锁,执行业务sql
——>5.然后和之前一样,它也要获取全局锁,但是全局锁此时已经被事务1拿了,所以它会进行自旋(300ms)
——>6.然后事务1如果此时要根据快照恢复数据,那么就需要DB锁,但是DB锁此时被其他事务拿了
——>7.死锁现象发生
——>8.还好其他事务重试失败后会释放锁资源,因为获取全局锁失败,那么后面的事务提交也进行不了
——>9.事务1再次拿到DB锁,可以进行快照恢复数据了;

在这里插入图片描述

其他事务不获取全局锁的一个情况(AT模式写隔离的实现)

利用了CAS的思想 :

实际上是有两份快照的:before-image、after-image

跟cas一样,before是我们要回滚目标的状态,而after是相当于验证的一个状态,如果满足after的内容,就可以设置为before;

如果不一样不满足的话,就会判断不能恢复回滚,那么我们可以记录异常发送警告;

在这里插入图片描述

总结:

AT:在第一阶段RM直接提交事务,释放数据库资源,不需要像XA模式那样,还需要将状态返回给TC事务协调者,还利用了全局锁实现读写分离:将表执行的事务储存起来,相当于一个标识;
并且**没有代码侵入,seata自动完成回滚和提交——>seata相当于RM资源管理器的一个代理**

在这里插入图片描述

实现AT模式

数据库表中:lock_table:全局锁,undo_log:放的是快照信息

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

可以再下单途中在业务代码中加上断点的方式查看数据库表中记录的快照信息和AT模式的全局锁信息 他们会在业务结束时自动销毁清理干净

TCC模式

在这里插入图片描述
在这里插入图片描述
那我们TCC模式是怎么保证一致性?

首先我们想想AT模式,在第一阶段,通过对数据库锁的获取完成事务,事务都是隔离的,所以有人成功有人失败,只有在二阶段完成回滚才能够保证数据的最终一致性,中间还是出现了软状态;

TCC模式,为什么就不需要锁了呢?我们AT模式是利用全局锁来保证一致性的——>执行sql后提交前上一道全局锁,那么其他事务的sql就执行不了进行自旋,超时就释放DB锁,而TCC解决利用了每个事务都是预留资源进行处理——> 第一个事务冻结的金额和第二个事务冻结的金额是不一样的,跟其他事务是没有关系的,那么回滚事务也是跟其他事务不影响的,不需要加锁(类似Semaphore)

简而言之就是把事务所用到的资源预留起来 等后面的结果再来判断是扣除还是释放,预留起来后数据库原表中的数据已经扣除了,所以其他的业务请求也不会有影响

在这里插入图片描述

TCC模式的关键在于有代码侵入:需要考虑Comfirm成功提交和Cancel数据回滚的编写

优点:1.TCC第一阶段直接提交事务,提交完直接释放数据库资源,AT的话也是直接执行,但是使用了全局锁来保存事务操作的一个状态,保证其他事务争夺不了,XA的话第一阶段就垃圾了,不会提交sql业务,需要把状态给到TC事务协调者进行判断是否回滚还是提交(是一提交或者回滚就是全局那种);
2.无需生成快照与全局锁,依赖的是一个补偿操作,因为事务直接提交的原则,所以其他事务是操作不到自己的,可用于非关系型数据库

在这里插入图片描述

TCC实现

具体模式还得根据场景来,比如TCC,就很像Semaphore,一般来说是对一个共享资源进行操作,比如停车场的停车位,库存…,像下单服务就不适合了,因为你每次调用都是一个新的订单;

一个事务是可以有多个模式实现的

在这里插入图片描述

在这里插入图片描述

我们怎么样去判断是否空回滚和业务悬挂?

利用两者相互判断 根据冻结金额的那张表来判断 在进行try业务前 先查询一下冻结金额的表中的数据是否为空 如果不为空则证明已经执行了CANCEL操作 则需要直接拒绝try的操作,反之在进行cancel业务前,需要根据事务id查询一下冻结金额的表中的数据是否为空 如果为空的话则证明try业务还没做,需要进行空回滚,同时也需要记录数据,new一个新的对象将冻结金额设为0,以及其他数据set进去

业务分析

在这里插入图片描述
在这里插入图片描述

我们可以在BusinessActionContext中获取里面的参数

事务表:表示事务冻结金额,冻结金额状态发生改变——>表示那部分被锁定

事务id,用户id,冻结金额和状态

在这里插入图片描述

业务方便代码的实现:

@Slf4j
@Service
public class AccountTCCServiceImpl implements AccountTCCService {

    @Autowired
    private AccountMapper accountMapper;

    @Autowired
    private AccountFreezeMapper accountFreezeMapper;

    @Override
    @Transactional
    public void deduct(String userId, int money) {
        //0.获取事务id
        String xid = RootContext.getXID();
        // 判断是否有冻结记录 有的话直接拒绝执行try业务
        AccountFreeze Freeze = accountFreezeMapper.selectById(xid);
        if (Freeze!=null) {
            //拒绝
            return;
        }
        //1.扣减可用余额
        accountMapper.deduct(userId, money);
        //2.记录冻结金额,记录事务状态
        AccountFreeze accountFreeze = new AccountFreeze();
        accountFreeze.setUserId(userId);
        accountFreeze.setFreezeMoney(money);
        accountFreeze.setState(AccountFreeze.State.TRY);
        accountFreeze.setXid(xid);
        accountFreezeMapper.insert(accountFreeze);

    }

    @Override
    public boolean confirm(BusinessActionContext ctx) {
        //0.获取事务id
        String xid = ctx.getXid();
        //1.删除数据
        int count = accountFreezeMapper.deleteById(xid);
        return count == 1;
    }

    @Override
    public boolean cancel(BusinessActionContext ctx) {
        //0.查询冻结记录
        AccountFreeze accountFreeze = accountFreezeMapper.selectById(ctx.getXid());
        String userId = (String) ctx.getActionContext("userId");
        //0.2.判断是否空回滚
        if (accountFreeze == null){
            accountFreeze = new AccountFreeze();
            accountFreeze.setUserId(userId);
            accountFreeze.setFreezeMoney(0);
            accountFreeze.setState(AccountFreeze.State.CANCEL);
            accountFreeze.setXid(ctx.getXid());
            accountFreezeMapper.insert(accountFreeze);
            return true;
        }

        //0.3 幂等判断
        if (accountFreeze.getState()==AccountFreeze.State.CANCEL){
            //已经处理过cancel了 无需重复业务
            return true;
        }

        //1.恢复可用余额
        accountMapper.refund(accountFreeze.getUserId(),accountFreeze.getFreezeMoney());

        //2.将冻结金额清零 改状态为cancel
        accountFreeze.setFreezeMoney(0);
        accountFreeze.setState(AccountFreeze.State.CANCEL);
        int count = accountFreezeMapper.updateById(accountFreeze);
        return count == 1;


    }
}

在这里插入图片描述

Saga模式

与TCC模式类似,但是TCC第一阶段只是将资源进行冻结,真正的去除还是在第二阶段的,而Saga模式是直接提交本地事务,第二阶段直接操作事务本身:成功则什么都不做,失败则通过编写补偿业务来进行回滚;

与AT相比没有用锁,与TCC比没有冻结资源,性能较好;

失败用自定义的补偿来写;

缺点:

没有保证隔离性,既没有隔离预留资源又没有上锁,容易出现脏写

在这里插入图片描述

总结

在这里插入图片描述

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

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

相关文章

C++学习——C++函数的编译、成员函数的调用、this指针详解

以下内容源于C语言中文网的学习与整理,非原创,如有侵权请告知删除。 从博文的分析中可以看出,对象的内存中只保留了成员变量,除此之外没有任何其他信息,程序运行时不知道 stu 的类型为 Student,也不知道它…

基于nodejs+vue校园失物招领平台设计与实现

科学技术日新月异的如今,计算机在生活各个领域都占有重要的作用,尤其在信息管理方面,在这样的大背景下,学习计算机知识不仅仅是为了掌握一种技能,更重要的是能够让它真正地使用到实目 录 摘 要 I ABSTRACT II 目 录 II…

数据库系统概论学习 1 绪论

1.1.1 数据、数据库、数据库管理系统、数据库系统 一、数据 Data 数据是数据库中存储的基本对象 定义:描述事物的符号记录称为数据,描述事物的符号可以是数字、文字、图像、图形、声音、语言等表现形式,它们都可以经过数字化后存入计算机。…

六分科技CEO李阳:精准定位助力汽车智能化普及

10月10日,2023四维图新用户大会在上海成功举办。大会现场,六分科技展示了基于PPP-RTK技术的“星璨”产品和软硬件一体化解决方案。同时在智能驾驶主题论坛上,六分科技CEO李阳受邀发表了以《精准定位助力汽车智能化普及》为主题的演讲。 高精度…

微信小程序clearInterval无法关闭时间间隔器问题解决

今天在微信小程序遇到了一个问题 我的代码是这样的 // 关闭动画函数 AnimationOff() {//定义时间间隔器clearInterval(this.animationTimer) }, DefineAnimation() {//定义时间间隔器this.animationTimer setInterval(() > {console.log("执行");}, 1000) },但是…

【Power BI】Power BI 入门指南:版本、下载和报表创建的步骤

文章目录 一、前言二、了解 Power BI 版本三、下载 Power BI Desktop四、如何开始使用 Power BI Desktop五、在 Power BI Desktop 中创建报表六、文末总结 一、前言 Power BI 是微软于 2013 年推出的产品,为一款商业智能与数据可视化工具。它通过引人注目的视觉效果…

企业如何选择安全又稳定的文件传输协议

企业无论是内部的数据共享,还是与外部的合作交流,都需要通过网络进行文件的传输和交换。然而,文件传输它涉及到多方面的因素,例如文件的大小、数量、类型、敏感性、传输距离、网络环境等。这些因素都会影响到文件传输的各个方面&a…

WEB应用程序编程接口API

使用Web API Web API是网站的一部分,用于与使用具体URL请求特定信息的程序交互。这种请求称为API调用。请求的数据格式以易于处理的格式(JSON,CSV)返回。 Git和GitHub Git是一个分布式版本控制系统,帮助人们管理为项目所做的工作…

Intellij 安装配置 lombok

Intellij 安装配置 lombok 用 lombok 能够减少 setter/getter/noArgsConstructor 这样的 boilerplate 代码,所以用起来还是比较方便的。 刚开始以为直接安装到 maven 里面就能用了,运行的时候发现 Getter, Data 这些 annotation 根本找不到&#xff0c…

*常用函数

文章目录 nn.PReLU() 激活函数 nn.PReLU() 激活函数 PReLU(Parametric Rectified Linear Unit), 顾名思义:带参数的ReLU 其中a代表的是可学习的参数 ReLU、PReLU的比较: 如果ai0,那么PReLU退化为ReLU; 如果ai是一个很小的固定…

c++可变参数模板

不要做一个清醒的堕落者文章目录 可变参数模板的简介什么是可变参数 模板参数包参数包数据的获取(函数递归获取)参数包的获取(逗号表达式获取) 可变参数的应用emplace 可变参数模板的简介 c11添加的新特性能够让你创建可以接受改变的函数模板和类模板,C98/03&#…

深入篇【C++】总结<lambda表达式>与<包装器和bind>的使用与意义

深入篇【C】总结<lambda表达式>与<包装器和bind>的使用与意义 一.lambda表达式1.使用语法2.底层本质3.应用意义 二.包装器(适配器)1.使用语法2.解决问题①3.解决问题②4.应用场景:指令操作 三.bind (适配器)1.调整参数位置2.绑定参…

Kafka基础入门

Kafka介绍 Kafka是什么? kafka是一种分布式的,基于发布/订阅的消息系统。 Kafka的特点 分布式,吞吐量高,发布订阅模式,轻量灵活,较长时间持久化 Kafka的应用场景 解耦 原先一个微服务是通过接口&…

2023年中国芝麻酱行业供需分析:需求量同比增长3.5%[图]

芝麻酱也叫麻酱,是把炒熟的芝麻磨碎制成的食品,有香味,作为调料食用。根据所采用的芝麻的颜色,可分为白芝麻酱和黑芝麻酱;芝麻酱是群众非常喜爱的香味调味品之一。食用以白芝麻酱为佳,滋补益气的以黑芝麻酱…

动态内存管理(malloc calloc realloc free)--- C语言

文章目录 写在前面1. malloc 和 free函数1.1 malloc函数介绍1.2 free函数介绍 2. calloc函数3. realloc函数4. 常见的动态内存错误4.1 对NULL指针的解引用操作4.2 对动态开辟空间的越界访问4.3 对非动态开辟内存使用free释放4.4 使用free释放一块动态开辟内存的一部分4.5 对同一…

Windows 移动设备管理

Windows 设备管理是指一组流程和工具,可帮助 IT 管理员简化企业中使用的Windows 设备的管理。管理企业中使用的 Windows 设备最好通过实施Windows MDM 解决方案来完成,以从单个控制台保护、管理和监视这些设备。Windows移动设备管理 (MDM&…

CakePHP 3.x/4.x反序列化RCE链

最近网上公开了cakephp一些反序列化链的细节,但是没有公开poc,并且网上关于cakephp的反序列化链比较少,于是自己跟一下 ,构造pop链。 CakePHP简介 CakePHP是一个运用了诸如ActiveRecord、Association Data Mapping、Front Contr…

美团Leaf使用

简介 在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识。如在美团点评的金融、支付、餐饮、酒店、猫眼电影等产品的系统中,数据日渐增长,对数据分库分表后需要有一个唯一ID来标识一条数据或消息,数据库的自增ID显然不…

全面解析找不到msvcr100.dll的解决方法,快速修复系统msvcr100.dll丢失问题!

在计算机的使用过程中,我们可能会遇到各种问题,其中之一就是“msvcr100.dll丢失”的问题。这个问题通常出现在运行某些程序或游戏时,提示找不到msvcr100.dll文件。这个文件是Microsoft Visual C 2010 Redistributable Package的一部分&#x…

学习 MPP 与 SMP 的区别,终于有人讲明白了

文章目录 01 SMPSMP 的典型特征如下:SMP 的缺点如下。 02 分布式MPP计算架构MPP 架构核心原理如下。 导读:当今数据计算领域主要的应用程序和模型可大致分为在线事务处理(On-line Transaction Processing ,OLTP)、决策…