Seata 笔记

news2024/11/17 9:56:14

Seata 笔记

分布式事务理论基础

CAP 定理

  • Consistency 一致性:用户访问分布式系统中的任意节点得到的结果都是一致的
  • Availability 可用性:用户和访问任意健康节点都必须得到响应而不是超时拒绝
  • Partition tolernance 分区容错性:出现独立分区时整个系统依然要对外提供服务
    • Partition 分区:因为网路故障或其他愿意导致分布式系统中的部分节点于其他节点失去连接,形成独立分区,独立分区内部节点可以同步数据而分区之间不能同步

分布式系统不可能同时满足这三个指标,最多满足两个

BASE 理论

BASE 理论时戳CAP的一种解决思路,其包括三个思想:

  • Basically Available 基本可用:分布式系统出现故障时,允许损失部分可用性,即保证核心可用
  • Soft State 软状态:允许系统在一定时间内出现中间状态,即临时的不一致性
  • Eventually Consistent 最终一致性:在软状态结束后,系统最终保持数据一致

基于 CAP 定理额 BASE 理论的几种模式:

  • AP 模式:各子事务分别执行和提交,允许出现结果不一致性,然后采用弥补措施恢复数据即可,实现最终一致
  • CP 模式:各个字数五执行后相互等待,同时提交,同时回滚,实现强一致性,但是事务等待过程中处于弱可用状态

Seata 架构

Seata 事务管理中的三个重要角色

  • TC(Transaction Corrdinator) 事务协调者:维护全局和分支事务状态,协调全局事务提交或回滚
  • TM(Transaction Manager) 事务管理器:定义全局事务的范围,开始全局事务,提交或ui滚全局事务
  • RM(Resource Manager) 资源管理器:管理分支事务处理的资源,与 TC 交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚

Seata 架构

Seata 提供的分布式事务解决方案:

  • XA 模式:强一致性分阶段事务模式,牺牲了一定可用性,对业务无侵入
  • AT 模式:最终一致分阶段事务模式,对业务无侵入,Seata 的默认模式
  • TCC 模式:最终一致的分阶段事务模式,对业务代码有侵入
  • SAGA 模式:长事务模式,对业务有侵入

XA 模式

XA 规范是 X/Open 组织定义的分布式事务处理(DTP, Distributed Transaction Processing)标准,描述了全局TM与局部RM之间的接口,几乎所有的主流数据库都对 XA 规范提供了支持,其分为两个阶段

  1. TM 通知 RM 执行各自的业务,RM 准备好后不提交,通知 TM 以就绪,若失败则发送失败通知给 TM
  2. TM 收到所有 RM 的就绪通知后通知各个 RM 提交事务,若第一阶段收到了失败通知则通知所有的 RM 进行回滚

XA模式

XA 模式优点:

  • 实现了分布式事务的强一致性,满足 ACID 原则
  • 常用数据库都支持 XA 模式,实现简单,对业务代码没有侵入

XA 模式缺点:

  • 第一阶段锁定数据库资源,等待第二阶段结束才释放,所以性能较差
  • 依赖数据库本身的事务,若数据库不支持则无法使用

XA 模式使用:

  1. 配置文件,对数据源进行代理,之后微服务的sql语句执行都会被数据源的代理对象拦截下来,RM 内部执行相应操作:
seata:
    data-source-proxy-mode: XA
  1. 全局事务入口方法处加上@GlobalTransactional注解

AT 模式

AT 模式和 XA 模式同样为分阶段提交的事务模型,其解决了 XA 模式中资源锁定时间过长的问题,其两个阶段为:

  1. TM 通知 RM 执行各自的业务,RM 执行业务并直接提交事务,将事务的更新信息存入 undo log(数据快照) 中,并向 TM 发送成功和失败通知
  2. 若所有 RM 都成功,则删除快照,否则根据快照进行回滚来恢复数据

AT模式

AT 模式与 XA 模式的区别:

  • XA 模式一阶段不提交事务,锁定资源, AT 模式一阶段提交事务,不锁定资源
  • XA 模式依赖数据库事务实现回滚,AT 模式利用数据快照进行回滚
  • XA 模式实现的为强一致性,而 AT 模式为最终一致性

AT 模式的脏写问题

为了解决 AT 模式的脏写问题,Seata 引入了全局锁来实现事务的写隔离,其由 TC 记录当前正在操作某行数据的事务,该事务持有全局锁,具备执行权

在全局锁实现中,TC 会创建一张表,存有事务 id,事务操作的表和表中的某个 id(对应事务操作的该表中的数据行),有点类似 MVCC

AT 模式中,数据快照保存由两份,一份为事务跟新数据前的快照(before-image)和事务提交前的快照(after-image),事务回滚时两份快照不一致时说明存在非 seata 管理的事务对数据进行了操作,说明数据无法恢复

AT 模式优点:

  • 一阶段直接提交数据库事务,释放数据库资源,性能相比 XA 模式更好
  • 利用全局锁实现隔离性
  • 框架自动完成事务的回滚和提交,对业务代码无侵入

AT 模式缺点:

  • 实现的是最终一致性,两阶段之间处于软状态,数据不一致
  • 框架的快照生成和处理会影响数据库性能

AT 模式的使用

  1. 在微服务关联的数据库中创建相应的快照 undo_log 表和全局锁 lock_table 表
  2. 配置文件:
seata:
    data-source-proxy-mode: AT
  1. 全局事务入口方法处加上@GlobalTransactional注解

TCC 模式

TCC 模式同 AT 模式一样,每个阶段都是独立事务,但是 TCC 模式需要手动编码来实现数据恢复,需要实现三个方法:

  • Try:资源的检测和预留
  • Confirm:完成资源操作业务,Try成功后调用,失败会重试
  • Cancel:预留资源释放,可以视作 Try 的反向操作,失败会重试

TCC 模式

TCC 模式优点:

  • 一阶段直接提交事务,释放数据库资源,性能好
  • 相比 AT 模式,无需生成快照,也无需使用全局锁,性能更好
  • 不依赖数据库事务,可以适用在非事务型数据库

TCC 模式缺点:

  • 需要手动实现 Try,Confirm,Cancel 三个方法,对业务代码由侵入
  • 需要考虑 Confirm 和 Cancel 的失败情况,需要做好幂等处理

TCC 空回滚和业务悬挂

当某分支事务的 try 阶段阻塞时,可能导致全局事务超时而触发二阶段的 cancel 操作。在未执行 try 操作时先执行了 cancel 操作,这是 cancel 不能做回滚,即空回滚

对于已经空回滚的业务,如果以后执行 try,就永远不可能 confirm 或 cancel,即业务悬挂,应当组织执行空回滚后的 try 操作,避免悬挂

解决:在数据库的表中添加一个额外的字段来记录事务状态,是出于 try,confirm 和 cancel 中的那个阶段

  • 判断空回滚:在 cancel 中,查询 try 的操作是否成功,如果查询不到数据则进行空回滚
  • 避免业务悬挂:在 try 中,查询 cancel 是否释放了资源,若查询到 cancel 已经执行,则拒绝执行 try 业务

TCC 模式的使用

编写 TCC 接口并编写实现类

@LocalTCC 
public interface TCCService {
    /**
     * try 方法
     * @TwoPhaseBusinessAction 注解中的name属性与方法名一致,commitMethod 属性 rollbaclMethod 属性用于指定 confirm 和 cancel 方法
     * @BusinessACtionContextParameter 注解标记的属性会放在上下文中,confirm 和 cancel 方法都能通过上下文拿到该属性信息
     **/
    @TwoPhaseBusinessAction(name = "prepare", commitMethod = "confirm", rollbaclMethod = "cancel")
    void prepare(@BusinessActionContextParameter(ParamName = "param") String param);

    /**
     * confirm 方法
     **/
    boolean confirm(BusinessActionContext context);

    /**
     * confirm 方法
     **/
    boolean cancel(BusinessActionContext context);
}

Saga 模式

Saga 模式是 Seata 提供的长事务解决方案,分为两个阶段:

  1. RM 直接提交本地事务
  2. 若所有的本地事务都成功则什么事都不做,若存在事务失败则执行手动编写的补偿业务来回滚

Saga 模式优点:

  • 可以实现基于事件驱动的异步调用,吞吐量高
  • 一阶段直接提交事务,释放数据库资源,性能好
  • 不用向 TCC 模式一样编写三个阶段的业务代码,实现相对简单

Saga 模式的缺点

  • 软状态持续事件不确定,时效性差
  • 没有事务隔离机制,存在脏写现象

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

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

相关文章

解决本地jar包导入maven

1、确定是否安装maven 2、输入导入命令 命令说明 <path-to-file>为你jar包所在的路径&#xff08;尽量简单并且不要含中文&#xff09; <group-id>为grouId号&#xff0c;与<artifact-id>组成唯一识别你jar包的坐标&#xff0c;当不在公共资源jar包中&#…

libbpf-bootstrap安卓aarch64适配交叉编译

1.为什么移植 疑惑 起初我也认为&#xff0c;像libbpf-bootstrap这样在ebpf程序开发中很常用的框架&#xff0c;理应支持不同架构的交叉编译。尤其是向内核态的ebpf程序本身就是直接通过clang的-target btf直接生成字节码&#xff0c;各个内核上的ebpf虚拟机大同小异&#xf…

万字解读 Android 车机核心 :CarService 的构成和链路~

前言 关于 Android 车机&#xff0c;之前分析过方控上自定义按键的输入机制和中控上旋钮输入的原理&#xff0c;但都局限于 Car Service 内 Input 相关模块。 一文了解 Android 车机如何处理中控的旋钮输入从实体按键看 Android 车载的自定义事件机制 本文将结合 Android 系…

LabVIEW开发感应电机在线匝间短路故障诊断系统

LabVIEW开发感应电机在线匝间短路故障诊断系统 工业中使用的超过85%的电动机是三相感应电动机。它们因其可靠性、设计便利性、高性能和过载能力而被广泛用于不同的应用&#xff0c;例如制造、加工、电力系统、运输等。无论它们的能力如何&#xff0c;它们都被认为是现代工业学…

Consider defining a bean of type问题解决

Consider defining a bean of type问题解决 Consider defining a bean of type问题解决 包之后&#xff0c;发现项目直接报错Consider defining a bean of type。 会有一些包你明明Autowired 但是还是找不到什么bean 导致你项目启动不了 解决方法一: 这个问题主要是因为项目拆包…

安卓 MeasureCache优化了什么?

安卓绘制原理概览_油炸板蓝根的博客-CSDN博客 搜了一下&#xff0c;全网居然没有人提过 measureCache。 在前文中提到过&#xff0c;measure的时候&#xff0c;如果命中了 measureCache&#xff0c;会跳过 onMeasure&#xff0c;同时会设置 PFLAG3_MEASURE_NEEDED_BEFORE_LAYOU…

【已解决】oracle获取最近2学年的数据

已解决 &#xff1a;oracle获取最近2学年的数据 SELECT * FROM (SELECT * FROM xx.JWXT_XSKB WHERE AND xn IN (‘2023-2024’,‘2022-2023’)); 问题 某某系统课表数据过大&#xff0c;要求只获取最近2学年的数据&#xff0c;不能写死。 思路 mysql 在子查询的WHERE子句中…

从0到1学会Git(第二部分):Git的本地操作和管理

写在前面:本文介绍了在本地仓库进行文件的处理以及本地的合并等操作。 前置知识:文件可以处在三个区域&#xff0c;分别为工作区&#xff0c;暂存区和本地仓库&#xff0c;我们此文的目标即是将文件存储在本地仓库中。我们可以将文件的区域理解为&#xff0c;cpu中&#xff0c…

苍穹外卖技术栈

重难点详解 1、定义全局异常 2、ThreadLocal ThreadLocal 并不是一个Thread&#xff0c;而是Thread的一个局部变量ThreadLocal 为每一个线程提供独立的存储空间&#xff0c;具有线程隔离的效果&#xff0c;只有在线程内才能取到值&#xff0c;线程外则不能访问 public void …

linux入门---动静态库的加载

目录标题 为什么会有动态库和静态库静态库的实现动态库的实现动静态库的加载 为什么会有动态库和静态库 我们来模拟一个场景&#xff0c;首先创建两个头文件 根据文件名便可以得知add.h头文件中存放的是加法函数的声明&#xff0c;sub.h头文件中存放的是减法函数的声明&#…

【每日运维】U盘启动盘安装 ESXi 6.7.0 安装卡在 loading /bnxtroce.v00

问题描述 ● ESXi 6.7.0 安装进度卡在loading /bnxtroce.v00 进度处 处理方法 ● 重新制作启动盘&#xff0c;写入方式改为&#xff1a;【USB-ZIPv2】 ● 设置服务器的 bios设置&#xff0c;启动方式改为【UEFI】 ● 重启开机安装即可

蛋白与蛋白互作预测 蛋白互作预测protein

How to prepare structures for HADDOCK? – Bonvin Labhttps://www.bonvinlab.org/software/bpg/structures/RosettaDock: 蛋白-蛋白复合物对接预测 - 知乎 (zhihu.com) 要进行LPR1-SEPP1复合物的结合亲和力预测&#xff0c;您可以按照以下步骤进行&#xff1a; 获取蛋白质结…

MySQL的Json类型个人用法详解

前言 虽然MySQL很早就添加了Json类型&#xff0c;但是在业务开发过程中还是很少设计带这种类型的表。少不代表没有&#xff0c;当真正要对Json类型进行特定查询&#xff0c;修改&#xff0c;插入和优化等操作时&#xff0c;却感觉一下子想不起那些函数怎么使用。比如把json里的…

vue实现列表自动滚动效果

效果如图&#xff1a; 1.下载插件 npm install vue-seamless-scroll --save 2.在main.js中引入注册 import scroll from vue-seamless-scroll Vue.use(scroll) 3.在页面中使用&#xff08;写一个固定的表头 el-table:show-header"status" 设置为false,自带的表头不…

嵌入式虚拟仿真实验教学平台使用教程之搭建课程计划

嵌入式虚拟仿真实验教学平台使用教程之创建课程计划 所谓「课程计划」就是将一系列实验按照一定的顺序组织成一个教学计划&#xff0c;和传统的教学计划模式比较类似。接下来我将为大家讲解如何通过该平台创建属于自己的课程计划。 嵌入式虚拟仿真实验教学平台提供了两种创建课…

Python综合案例(基本地图使用)

一、基本地图的使用 基本代码&#xff1a; """ 演示地图可视化的基本使用 """ from pyecharts.charts import Map from pyecharts.options import VisualMapOpts# 准备地图对象 map Map() # 准备数据 data [("北京", 99),("…

js获得相对路径文件,并上传到服务器

如何通过js获得相对路径文件 已知一个相对路径文件&#xff0c;如何使用js将该文件读取为File格式&#xff0c;最后上传到服务器中呢。 1.最简单的解决方案——fetch 代码 import ./index.scss// js通过相对路径获取文件 function FetchGetLocalFile() {const fetchLocalFile …

【0904作业】QT 完成登陆界面跳转到聊天室+完成学生管理系统的查找和删除功能

一、完成登陆界面跳转到聊天室 1> 项目结构 2> 源码 ① .pro ②main #include "mywnd.h" #include"chatCli.h" #include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);MyWnd w;w.show();Form f;QObject::co…

【LeetCode算法系列题解】第51~55题

CONTENTS LeetCode 51. N 皇后&#xff08;困难&#xff09;LeetCode 52. N 皇后 II&#xff08;困难&#xff09;LeetCode 53. 最大子序和&#xff08;中等&#xff09;LeetCode 54. 螺旋矩阵&#xff08;中等&#xff09;LeetCode 55. 跳跃游戏&#xff08;中等&#xff09; …

【深入解析spring cloud gateway】07 自定义异常返回报文

Servlet的HttpResponse对象&#xff0c;返回响应报文&#xff0c;一般是这么写的&#xff0c;通过输出流直接就可以将返回报文输出。 OutputStream out response.getOutputStream(); out.write("输出的内容"); out.flush();在filter中如果发生异常&#xff08;例如…