事务的原理

news2024/12/28 5:21:29

1. 什么是事务

事务就是一个包含多个步骤的事情,这些步骤要么都做好,要么都别做。

2. ACID

事务都跟ACID相关,注意这里说的是“相关”,而不是一定都“满足”。全都严格满足,是“刚性事务”,部分满足或一定程度满足,是“柔性事务”。 ACID展开来说是:

  • A(Atomic)原子性:事务的每一步要么都做好,要么都别做。
  • C(Consistency)一致性:事务从一个状态变到另一个状态,不能停止在中间状态。比如你只能在家、或在公司,不能停在路上(可以停一段时间,但不能成为你的终态)。
  • I(Isolation)隔离性:多个事务执行过程中的互相影响的情况。比如你和你同事分别去公司,路上碰见可能聊几句话(脏读、幻读、不可重复读),也可能碰到了装作不认识。
  • D(Durability)持久性:事务一但成功,就被永久保留下来。比如你到公司了,只要没有其他事情发生:同事来看,你在;老板来看,你也在;老板上午来看,你在;老板晚上10点来看,你也在。

3. CAP

  • C:一致性
  • A:可用性
  • P:分区容错

分布式场景下,P必须满足,否则就是单机系统了。

分布式下,A和C只能满足一个。

  • CP:追求强一致性,一般像配置中心,是CP模式,如zookeeper、etcd。
  • AP:最终一致性,追求高可用,BASE,一般像注册中心。

4. BASE

在互联网服务中,一般对可用性要求很高,比如5个9的SLA。在这些场景的分布式事务中,对AP进行了延伸,保障高可用,容忍一定时间的中间状态,只要能最终一致性就可以,这就是BASE。

5. 刚性事务和柔性事务

5.1. 刚性事务

严格满足ACID。

5.2. 柔性事务

  • A:严格满足
  • C:部分满足
  • I:部分满足
  • D:严格满足

6. XA协议

数据库的一种接口协议,一般是用于数据库事务的。

它所定义的3种角色,在其他分布式事务中也可以参考使用。

  • AP:应用服务。
  • TM:事务管理器,有些地方也叫事务协调者。
  • RM:资源管理器。

7. 分布式事务的方案

7.1. 两阶段提交(2PC)

  • 1阶段prepare:事务参与方开启事务(如数据库做为参与方,这一阶段会开启数据库事务,记录undo、redo信息),但不提交。
  • 2阶段commit:1阶段都准备好的话,这个阶段就提交,否则这个阶段就回滚。

2b37f71c028546b78b7b19f558f03198.jpg

2PC的问题主要是同步阻塞事务时间长。每个RM在第一阶段都要开启事务(就像DB里start了一个事务,但没有commit,就阻塞在这里了,并且每个RM都要等所有其他RM全部开启好事务),在第二阶段才会提交或回滚事务。如果有一个RM开启事务很慢,其他RM就要开启着事务等着它,平白无故在那里等它。

比如有个人在深山老林,网络很差,跟其他人一起协商做个事,其他人要等他半天。

7.2. 三阶段提交(3PC)

  • 1阶段canCommit:RM上不开启事务,只是问问每个RM,能不能行。
  • 2阶段prepare:对应2PC的1阶段。
  • 3阶段commit:对应2PC的2阶段。

5a756590ffbd42c4a3f373aae8f6cd88.jpg3PC对2PC做了个优化,先询问一下每个RM基本资源是不是准备好了,并不开启事务,这会大大降低由于下一阶段由于部分RM异常(包括RM本身异常和RM对应的网络异常)所导的其他RM白白开启事务的成本。

比如有个人在深山老林,网络很差,跟其他人一起协商做个事,其他人发现他网不好,这个事情就先不做了(回滚),大家也不会干耗在那里等他半天,才决定不做。

虽然3PC对2PC做了优化,但实际用得最多的还是2PC,因为3PC有点复杂。

7.3. TCC

TCC是Try-Confirm-Cancel的简称,属于两阶段提交:Try是一阶段,Confirm/Cancel是二阶段。

TCC的思路是减小RM上事务影响范围。

  • Try:TCC只预留部分资源,不像2PC,第一阶段在RM上就把一个大事务给开启了。比如交易的时候TCC先“预扣款”,即冻结部分钱,这样你的其他钱还能被其他事务使用;而2PC的第一阶段上来就把你整个银行卡冻住,你其他事情也干不了了。
  • Confirm:执行真正的业务提交,它是基于Try阶段预留的资源进行的。比如在上述交易场景中,Confirm阶段会将冻结的钱正式扣除,并进行其他相关业务操作,如生成订单等。
  • Cancel:在Try或者Confirm阶段出现问题,都会执行Cancel阶段,将资源状态恢复到事务执行前。比如上述交易场景出现问题,Cancel阶段就把冻结的钱再“还”回去。这也可以算作一种“补偿”机制。
  1. Try和Confirm阶段分别要提交哪些事务,都是根据业务自己来决定的,而且因为提交了事务,在Cancel阶段要回滚就只能业务上自己处理了,所以TCC一般是业务上自己实现的,没法靠数据库帮你回滚。
  2. TCC对业务入侵较多,因为TCC一般是业务上自己实现的。

7.4. AT模式

automatic transaction,自动事务。也是一种2PC的变形。

7.4.1. 数据准备阶段(1阶段)

在RM上拦截业务SQL,保存SQL执行前后的数据镜像(分别叫“前镜像”和“后镜像”),这些操作是在事务范围内进行的,确保数据的一致性。然后把这些镜像和事务相关信息存到undo_log中,用于后续回滚。

7.4.2. 事务提交阶段(2阶段)

如果每个RM的事务都顺利提交,就可以删除undo_log中的记录。

7.4.3. 事务回滚阶段(2阶段)

如果某些(个)RM事务执行有问题,则根据undo_log中的“前镜像”“后镜像”等信息,对已执行操作进行逆向操作。

7.4.4. AT的特点总结

  • 锁定少:一阶段不强锁定,通过数据前后镜像来回滚,RM锁定粒度和时长与传统2PC不同。
  • 无侵入:对业务代码无侵入,开发者无需关心事务的具体实现细节,只需关注业务逻辑本身。
  • 高性能:可以把2阶段异步化,这样只处理了一阶段就返回响应,然后异步慢慢处理二阶段。

7.5. 事务消息

事务消息是一种分布式系统中保证事务一致性的消息处理机制。属于一种特殊的2PC。

7.5.1. 正常过程

  1. 第一步,发送半消息:生产者把消息发到消息中间件,此时消息中间件不会把此消息投给消费者。
  2. 第二步,成功,则提交消息:生产者执行本地事务,如果没问题会提交给消息中间件一个确认的消息,消息中间件保证(重试、死信队列)把消息投递给消费者。
  3. 第二步,失败,则回滚消息:本地事务执行失败,生产者会向消息中间件发送一个回滚消息,消息中间件会删除之前暂存的半事务消息,这样消费者就不会收到该消息。

“半消息”一般都是完整的消息,只是后面还要“提交”一下才能被消费者看到,所以被叫做“半消息”

7.5.2. 异常处理

  • 消息中间件一直未收到确认或回滚的消息:比如网络异常或者生产者突然挂了,不同的消息中间件的处理方式会有所不同。如:
    • 回滚该半消息:将其从消息存储中删除
    • 使用回调:消息中间件定期(或超时)来查询生产者上的一个回调函数,来觉得是回滚还是提交半消息。如果查询次数太多(相当于重试太多),会丢掉这个消息,或者把它记录到某个地方(比如死信队列)。
  • 消息中间件收到确认或回滚消息后,投递给消费者失败:这要靠消息中间件的机制来确保一定要投递出去了,一般消息中间件会重试。
  • 由于消息中间件会重试,所以消费者可能会收到多次相同的消息,所以消费者需要保证幂等性消费。

事务消息,要重点记住和理解“两次提交”消息和“回调查询”的机制

7.6. SAGA模式

  • 把事务拆分成多个本地事务,按一定顺序执行。
  • 每个本地事务,都要有一个对应的补偿事务。

比如有A、B、C三个事务,对应a、b、c三个补偿事务,正常执行顺序是ABC,当执行到C失败的时候,就要执行b、a,把事务回退。

SAGA模式的特点:

  • 灵活:可灵活定义事务拆分方式和补偿事务。它不依赖事务协调器,本地事务可独立开发部署。
  • 高性能:被拆分的这些本地事务可以异步执行,提高系统的并发和速度。
  • 对业务侵入性较强:与其他一些分布式事务解决方案相比,SAGA模式需要开发者手动编写每个本地事务及对应的补偿事务,对业务代码有一定的侵入性。

8. 分布式事务方案对比

a7f56629eba34a84b3fa0e85e3552dbf.png

9. 事务悬挂与空回滚

9.1. 事务悬挂

事务悬挂就是事务没有正常走到终态。

比如猴子要么在树上,要么在地上,是正常的终态,但它“悬挂”在树上,始终不是长久之计。

通常,事务悬挂是发生在某些事务参与方一阶段正常、二阶段不正常的情况下。

一般来说,成熟的事务框架会保证业务逻辑正常的时候不会发生悬挂,但业务逻辑有问题,就没法保证了。比如参与方在二阶段明明不正常,它还给TM(transaction manager)返回正常。

9.2. 空回滚

一般是RM上的一阶段还没处理完(或没处理,比如网络延时导致先收到二阶段的请求),二阶段的回滚请求就过来了,这样回滚的就是空的东西。

如事务消息中,生产者发送半消息后,由于网络原因,消息中间件没有收到该半事务消息,但消息中间件触发了回滚操作,这就是空回滚。

9.3. 空回滚容易导致事务悬挂

RM上先执行了二阶段的回滚(空回滚),才收到一阶段的请求,一阶段的请求再也不会被二阶段处理,就悬在那里了。

9.4 事务悬挂的解决方法

9.4.1. 方法1. 一阶段必须先执行完,才能执行二阶段

这要求一阶段有重试机制,其实就是把一二阶段串行起来了,必须先1,再2。

9.4.2. 方法2.双插方案

  • 一阶段开始前插入一个“事务id”且状态是“一阶段”的记录,然后锁住所有“事务id”的记录,看下有没有状态是“回滚”的,如果没有,正常执行一阶段,否则说明有些RM先回滚了,那就不执行一阶段了。
  • 二阶段回滚前插入一个“事务id”且状态是“回滚”的记录,然后锁住所有“事务id”的记录,再执行回滚。

本质就是让一二阶段感知到对方,且同一个事务不能并行跑一二阶段。

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

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

相关文章

240908-Python代码实现6种与DBGPT-Knowledge-API的交互方式

A. Chat模式 # import asyncio # from dbgpt.core import ModelRequest # from dbgpt.model.proxy import OllamaLLMClient# clientOllamaLLMClient()# print(asyncio.run(client.generate(ModelRequest._build("qwen2:1.5b", "你是谁?"))))imp…

Debug-027-el-tooltip组件的使用及注意事项

前言: 这两天,碰到这个饿了么的el-tooltip比较多。这个组件使用起来也挺简单的,常用于展示鼠标 hover 时的提示信息。但是有一些小点需要注意。这里不再机械化的介绍文档,不熟悉的话可以先看一下: https://element-pl…

这个隐藏功能,90%的人还不知道!可一键直达40+AI应用!含Kimi、腾讯元宝、秘塔AI等常用AI工具

大家好,我是程序员X小鹿,前互联网大厂程序员,自由职业2年,也一名 AIGC 爱好者,持续分享更多前沿的「AI 工具」和「AI副业玩法」,欢迎一起交流~ 又是被粉丝感动的一天。 昨天一位读者加到我,是一…

基于Java+SpringBoot+Vue+MySQL的美容美发管理系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于SpringBootVue的美容美发管理系统【附源码文档】、前后…

音频创作无界限:全球热门剪辑软件深度评测

如果是一个音乐爱好者肯定会有过想要录制自己音乐作品的想法吧。这个操作放在早些年可能有些难度,但是现在是科技告诉发展的时代,互联网上有不少在线音频剪辑工具可以供我们选择。这次我们就一起来探讨有什么适合音频剪辑的工具。 1.福昕音频剪辑 链接…

3.C_数据结构_栈

概述 什么是栈: 栈又称堆栈,是限定在一段进行插入和删除操作的线性表。具有后进先出(LIFO)的特点。 相关名词: 栈顶:允许操作的一端栈底:不允许操作的一端空栈:没有元素的栈 栈的作用: 可…

【机器人工具箱Robotics Toolbox开发笔记(一)】Matlab机器人工具箱简介

MATLAB是一款被广泛应用于科学计算和工程领域的专业软件。它的全称为Matrix Laboratory(矩阵实验室),因为其最基本的数据类型就是矢量与矩阵,所以在处理数学和科学问题时非常方便,可用于线性代数计算、图形和动态仿真的…

系统架构的演进:同步通讯到异步通讯的过渡

系统架构的演进:同步通讯到异步通讯的过渡 一 . 同步通讯 VS 异步通讯1.1 同步调用方案① 耦合度高② 性能下降③ 资源浪费④ 级联失败 1.2 异步调用方案① 同步解耦② 性能提升 , 吞吐量增加③ 服务没有强依赖 , 不必考虑级联失败问题④ 流量削峰 1.3 小结 二 . 三…

【C++】STL学习——stack和queue的讲解(了解适配器)

目录 stack介绍queue介绍适配器stack的模拟实现queue模拟实现deque(了解) stack介绍 stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行 元素的插入与提取操作。stack是作为容器适配器被…

Java | Leetcode Java题解之第393题UTF-8编码验证

题目&#xff1a; 题解&#xff1a; class Solution {static final int MASK1 1 << 7;static final int MASK2 (1 << 7) (1 << 6);public boolean validUtf8(int[] data) {int m data.length;int index 0;while (index < m) {int num data[index];…

算法练习题18——leetcode240搜索二维矩阵||(二分)

题目描述 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 代码 class Solution {public boolean searchMatrix(int[][] matrix, int target) {for(int[…

双指针(6)_单调性_查找总价格为目标值的两个商品

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 双指针(6)_单调性_查找总价格为目标值的两个商品 收录于专栏【经典算法练习】 本专栏旨在分享学习C的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#…

DuPL: Dual Student with Trustworthy Progressive Learning for Robust WSSS

摘要 近年来&#xff0c;具有图像级标签的单阶段弱监督语义分割(WSSS)因其简化了其繁琐的多阶段语义分割而获得了越来越多的关注。由于类激活图(Class Activation Map, CAM)固有的模糊性&#xff0c;我们观察到一级管道经常会遇到由错误的CAM伪标签引起的确认偏差&#xff0c;…

基于SpringBoot的图书馆座位预约系统+小程序+LW参考示例

系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…

继电器的使用

本文为大家讲一下继电器的常规使用. 添加 在菜单中选择 “绘制–无源元件–添加继电器(relay)” 以添加继电器. 或者用 shiftr(大写) 这个快捷键 继电器由一个线圈和该线圈所控制的铁质弹性开关(衔铁)组成. 原理 它的原理如下: 上面的铁质弹性开关, 默认情况下在弹力作用下…

java基础概念22-抽象类

一、抽象类的引入 1-1、封装 问题&#xff1a;javabean越来越多。重复的内容越多——继承 1-2、继承 二、抽象类、抽象方法 一个方法抽取到父类中&#xff0c;不确定方法体——抽象方法 定义了抽象方法的类——抽象类。 在Java中&#xff0c;抽象类是一种特殊的类&#xff0c…

博士生锻炼记录:2024.9.8

读博三年来感觉身体状况大不如前&#xff0c;虽然博士生的主要任务就是做课题和发文章&#xff0c;但是身体健康也是不容忽视的一环&#xff0c;一个好的身体是做好任何事情的基础&#xff0c;我们应该在不影响身体健康的前提下努力做课题。 这周初去参加了一个体成分测量的活…

Python编码系列—Python项目管理:掌握高效工具与实践

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

YOLOv9改进策略【Neck】| 使用CARAFE轻量级通用上采样算子

一、本文介绍 本文记录的是利用CARAFE上采样对YOLOv9的颈部网络进行改进的方法研究。YOLOv9采用传统的最近邻插值的方法&#xff0c;仅考虑子像素邻域&#xff0c;无法捕获密集预测任务所需的丰富语义信息&#xff0c;从而影响模型在密集预测任务中的性能。CARAFE通过在大感受…

Linux服务器Java启动脚本

Linux服务器Java启动脚本 1、初版2、优化版本3、常用脚本仓库 本文章介绍了如何在Linux服务器上执行Java并启动jar包&#xff0c; 通常我们会使用nohup直接启动&#xff0c;但是还是需要手动停止然后再次启动&#xff0c; 那如何更优雅的在服务器上启动jar包呢&#xff0c;让我…