架构中的事务处理

事务的ACID中AID是手段,C是目的

原子性,隔离性,持久性是因,是手段,而一致性是由于事务遵照了原子性,隔离性,持久性所呈现的结果。

单数据源的一致性

当服务只使用一个数据源时,通过AID来获得一致性是最经典的做法,也是相对容易的。

外部一致性

当一个服务使用多个数据源,甚至多个服务涉及多个不同的数据源,这种多数据源的一致性问题,称为“外部一致性“。

对于外部一致性:在可承受下尽量获得强度大的一致性保障

在单个服务使用单个数据源的场景下的事务保证一致性

事务的一致性依赖于数据源,开发人员最多只能对接口做一层标准化的包装(JDBC接口),并不能深入参与到事务的运作过程中。
事务的开启,终止,提交,回滚,甚至是隔离级别,全部都要依靠底层数据源的支持。

数据库如何通过原子性,隔离性和持久化实现事务的一致性

数据库面临的原子性问题

原子性即事务要么生效,要么不生效,不会存在中间状态。
但是数据先存在内存上(断电全无),存在将数据写入磁盘的过程(中间状态,破坏了原子性)。
具体来说存在两种情况:

  1. 未提交事务,但是已经写入数据到磁盘,此时崩溃。因为没有提交事务,所以重启后需要将磁盘中的数据恢复成没有修改过的样子。
  2. 已提交事务,但是还没将数据写入磁盘,此时崩溃。因为提交了事务了,所以重启之后需要将未写入的数据写入磁盘。
崩溃无法避免,只能通过将事务修改的数据提前备份从而实现恢复
通过提交日志(Commit logging)(也叫做redo log)实现提前备份从而保证了原子性

在事务从内存写入磁盘之前,先将事务内容写入提交日志中并且持久化到磁盘,这样崩溃的时候也能通过提交日志,看到这个事务到底是提交了没有,这个事务的内容是什么。
崩溃恢复中,如果事务没有写入提交日志提交标志,那么这个事务就是提交失败的,需要回滚,如果写入提交标志,那么就是提交成功的。

提交日志策略在日志写入磁盘之前不允许数据写入磁盘,造成了资源浪费

STEAL:对于事务提交和数据写入硬盘的顺序:允许数据先日志写入称为steal,不允许称为NO-STEAL,Commit Logging就是NO-STEAL

Write-Ahead Logging:通过undo-log实现STEAL

当数据写入磁盘前先写入undolog,如果崩溃后,按照undolog对提前写入的数据变动进行擦除。

完整的Write-Ahead Logging在崩溃恢复
  1. 分析阶段:找出没提交但是写入的数据,找出提交了但是没有写入的数据。
  2. redo阶段:从checkpoint开始,将提交了的事务的数据都写入磁盘中。
  3. undo阶段:将没提交的事务的数据都撤销(通过undolog记录的undo值)

数据库由于并发导致隔离性问题,通过锁解决

隔离性保证了各个事务各自读,写的数据互相独立,不会彼此影响。
但是数据库并发执行,为了保证隔离性就引入了锁。

现代数据库使用三种锁实现了各种隔离级别,隔离级别是因为使用的锁不同而导致的
  • 写锁:数据加上写锁,只有持有写锁的事务才能修改数据,而且也不能添加读锁。
  • 读锁:多个事务可以对一个数据添加多个读锁,加读锁后就不能加写锁了,但是仍然能被读取。
  • 范围锁:相当于对一个范围(不是一组数据)加了写锁了。eg. select * where price < 100 for undate;
    只有需要修改数据时才加写锁,只有读数据的时候才会考虑加读锁(读未提交不加读锁)。
隔离级别1:串行化

给所使用的数据加三种锁,即可实现串行化。通过两阶段锁来加锁。

隔离级别2:可重复读

给事务涉及的数据加读锁和写锁,且一直持有直到事务结束,但是不加范围锁。
此时就会出现范围查询的结果在一个事务中不同,因为没有加范围锁。

隔离级别3:读已提交

给事务涉及的数据加的写锁持续到事务结束,但是加的读锁在查询语句结束后会立即释放。
这样的话,T1修改了数据a,T2只有等T1事务提交后T1释放了写锁,才能给数据a添加读锁进行读操作。
所以称为读已提交。

隔离级别4:读未提交

只会对事务涉及的数据加写锁,在事务结束后释放。
所以多个事务并发,想读就读。

幻读,不可重复读,脏读,都是一个事务读的过程,其他事务写造成的

针对这个问题,提出了MVCC(针对读-写冲突的优化)

新老版本共存,从而达到读数据时不加锁的目的。
数据库中的每一行数据,都记录了两个看不见的字段:create_version , delete_version,记录的是事务ID。
只写入版本数据行,不删除数据。

  • 插入数据时,添加数据作为新的一版本行,在这条数据的create_version记录插入的事务ID,delete_version为空。
  • 删除数据时,复制数据作为新的一个版本行,delete_version为事务ID,create_version为空。
  • 修改数据时,当作”删除旧数据,插入新数据的组合“,添加两个版本行,一个按删除,一个按插入数据。

通过隔离级别来确认读取哪个版本行:

  • 可重复读:读取craete_version<=事务ID的最新数据行
  • 读已提交:读取最新版本即可

单个事务使用多个数据源下的事务一致性

分布式事务下的两阶段提交实现事务一致性

准备阶段

协调者询问所有事件源准备好提交了吗(对于数据源,就是日志持久化完成,数据持久化完成,就差一条commit recode了)

提交阶段

所有参与者都回复了可以提交了,协调者发送提交命令,完成提交。

缺点

任何一个参与者失败则全部回滚。
网络必须没有问题。
所有参与者的执行事务必须等待最终命令才能提交,最终命令之前会加锁。

三阶段提交实现事务一致性

CanCommit,PreCommit,DoCommit
会在执行分布式事务之前,询问各数据源能否执行事务。
避免了有些数据源本身根本就不想执行事务,还需要其他数据源参与一轮回退。

缺点和两阶段相同

多个服务使用一个数据源

因为一个服务集群中数据库的压力总是最大的,所以首先就不推荐使用。
这种场景,使用消息队列,让数据库作为消息队列的消费者来消费事务。

分布式事务

在分布式系统中CAP只能满足两个:
强一致性:多节点数据任何时刻完全相同
可用性:消息同步阶段服务就不可用了
分区容忍性:网络通信不是永远可靠的

分布式事务机制:通过消息队列实现最大努力交付:将消费放到消息队列,失败就重复直到成功

没有回滚的概念,只能成功,或者失败(需要人工介入)。
事务的消费者会在执行事务过程中一直显示”消费中“。
将多个数据源的消费消息传递给消息队列,在消息队列中,每个消息会不断去消费源重复消费(通过UUID确保幂等)直到成功。
只有当多个数据源的数据消费都完成后才会将事务调整者撤去”消费中“,变为一致性。

缺点

会因为不能回滚,发生超卖(一个物品卖给多个用户,多个用户显示”消费中“),需要人工介入处理。

分布式事务机制:TCC(类似银行家算法,在消费前预估能否消费并且加锁)

通过卖出商品前给商品加锁,其他用户不能购买,从而无法超卖。
过程:

  1. try(获取资源,如果成功给资源加锁)
  2. confirm(如果try获取资源成功,执行事务)
  3. cancel(如果try获取资源失败,释放资源,事务失败)

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

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

相关文章

Linux 驱动 中断(一)

中断是指计算机运行过程中&#xff0c;出现某些意外情况需主机干预时&#xff0c;机器能自动停止正在运行的程序并转入处理新情况的程序&#xff0c;处理完毕后又返回原被暂停的程序继续运行。 在 Linux 中&#xff0c;中断处理是操作系统与硬件设备之间通信的重要方式之一。Li…

边缘计算网关在机床生产中的应用-天拓四方

随着工业4.0的推进&#xff0c;物联网&#xff08;IoT&#xff09;技术在各个工业领域中的应用日益广泛。特别是在机床行业&#xff0c;物联网技术的引入不仅提高了生产效率&#xff0c;还实现了对机床设备的实时监控和远程维护。在这一背景下&#xff0c;边缘计算网关的角色愈…

android开发实例,retrofit解析

面试官的问题&#xff1a; &#xff08;1&#xff09;问&#xff1a;点击一个图标到这个应用启动的全过程&#xff08;前面是项目经验没啥好说的&#xff09;。 答&#xff1a;点击图标后通过startActivity远程调用到ams中&#xff0c;ams中将新启动的activity以activityrecor…

【丹尼早晚安】打卡第七天,英语学习笔记

成分颜色主语&#xff08;subject&#xff09;橙色谓语&#xff08;predicate&#xff09;蓝色宾语&#xff08;object&#xff09;红色定语&#xff08;attribute&#xff09;紫色状语&#xff08;adverbial&#xff09;棕色补语&#xff08;complement&#xff09;粉色 早上…

2024新版SonarQube+JenKins+Github联动代码扫描(2)-SonarQube代码扫描

文章目录 前言一、docker方式安装sonar二、启动容器三、创建数据库四、启动sonarqube五、访问sonar六、如果访问报错-通过sonar日志定位问题七、修改密码八、汉化&#xff08;看个人选择&#xff09;九、扫描十、我遇到的Sonar报错以及解决办法 总结 前言 这是2024新版SonarQu…

Python算法题集_分割回文串

Python算法题集_分割回文串 题131&#xff1a;分割回文串1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【参数回退回溯单行回文检测】2) 改进版一【参数回退回溯lambda回文检测】3) 改进版二【参数回退回溯函数回文检测】4) 改进版三【堆栈回退…

重绘和重排应该如何理解和避免

重绘和重排是浏览器渲染过程中的两个重要概念&#xff0c;它们都会影响页面的性能。以下是对重绘和重排的详细理解以及如何避免它们的建议&#xff1a; 一、重绘&#xff08;Repaint&#xff09; 1.1 理解 重绘是指元素的几何属性不变&#xff0c;页面的外观发生变化&#x…

Python - getpass

文章目录 关于 getpass基本使用语法说明其它 关于 getpass getpass 是 Python 自带标准库 Python 官方文档 - getpass https://docs.python.org/3/library/getpass.html 基本使用 我们在看视频教程中&#xff0c;老师如果不想在代码中暴露 token、密码之类的信息&#xff0c…

Leet code 611 有效三角形个数

简单有效的思路&#xff1a;双指针解法 比如给出一个nums{4&#xff0c;3&#xff0c;2&#xff0c;4&#xff0c;5&#xff0c;6&#xff0c;8&#xff0c;10} 先将nums排序 -> { 2, 3, 4, 4, 5, 6, 8, 10} for(int inums.size()-1;i>2;i--) i的下标为当前最大值的下…

管理npm源:如何使用nrm工具提升你的开发效率

在 JavaScript 和 Node.js 的开发过程中&#xff0c;npm&#xff08;Node Package Manager&#xff09;扮演着至关重要的角色&#xff0c;它是管理项目依赖的主要工具。然而&#xff0c;由于网络环境的差异&#xff0c;特别是在中国大陆&#xff0c;直接使用 npm 官方源可能会遇…

【C++】继续学习 string类 吧

开始使用 string类 吧 1 继续学习1.1 扩容机制1.2 string类对象的访问及遍历操作1.3 string类对象的修改操作1.4 其他一些成员函数 2 实践解决问题&#xff1a;Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读&#xff01;&#xff01;&#xff01;下一篇文章见&…

钉钉h5应用 环境报错Error: Do not support the current environment:notInDingTalk

钉钉h5应用 环境报错 Error: Do not support the current environment&#xff1a;notInDingTalk problem Error: Do not support the current environment&#xff1a;notInDingTalk reason 前端页面运行在普通浏览器 solution 需要将h5页面在后台发布后&#xff0c;在钉…

L2-001 紧急救援(Java)

作为一个城市的应急救援队伍的负责人&#xff0c;你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候&#xff0c;你的任务是带领你的…

使用awk和正则表达式过滤文本或字符串 - 详细指南和示例

当我们在 Linux 中运行某些命令来读取或编辑字符串或文件中的文本时&#xff0c;我们经常尝试将输出过滤到感兴趣的特定部分。这就是使用正则表达式派上用场的地方。 什么是正则表达式&#xff1f; 正则表达式可以定义为表示多个字符序列的字符串。关于正则表达式最重要的事情之…

自建Redis蜜罐以捕获和分析潜在攻击

一、引言 随着网络攻击的日益频繁和复杂&#xff0c;传统的防御措施往往难以应对。蜜罐作为一种主动防御技术&#xff0c;通过模拟有价值的服务来吸引攻击者&#xff0c;从而收集和分析攻击数据&#xff0c;提高网络安全性。本文将介绍如何自建一个Redis蜜罐&#xff0c;以捕获…

微服务-高级篇

微服务-高级篇 一.微服务保护1.初识Sentinel2.微服务整合Sentinel3.限流4.隔离和降级5.授权规则6.规则管理模式 二、分布式事务1.什么是分布式事务&#xff1f;2.理论基础3.部署与集成Seata4.Seata的四种模式5.Seata高可用 三、分布式缓存1.Redis持久化2.搭建主从架构与哨兵模式…

纷争不断的低代码平台

在IT行业&#xff0c;技术的更新换代总是伴随着争议和质疑。低代码平台&#xff0c;作为一种旨在简化软件开发过程的技术&#xff0c;也不例外。但是&#xff0c;就像任何新兴技术一样&#xff0c;真正的价值往往在于实际应用中得到验证。今天&#xff0c;我要分享的故事&#…

【理解机器学习算法】之Nearest Shrunken Centroid(纯Python)

从头开始实现最近缩小质心&#xff08;NSC&#xff09;分类器涉及理解它如何通过将质心缩小到所有类的总质心方向来修改基本的最近质心方法&#xff0c;有效地执行特征选择。这种方法特别是在微阵列预测分析&#xff08;PAM&#xff09;中的应用而闻名。这里&#xff0c;我们将…

13. Nginx进阶-平滑升级

简介 注意点 当前服务器不关机&#xff1b;用户可以正常访问&#xff1b;由低版本升为高版本&#xff1b;只支持编译安装的nginx&#xff1b; 升级的原理 在不停掉老进程的情况下&#xff0c;启动新进程。老进程负责处理仍然没有处理完成的请求&#xff0c;但不接受新请求。…

docker 安装 Jenkins

一、安装 jenkins 中文文档&#xff1a; https://www.jenkins.io/zh/doc/book/installing/#docker jenkins 提供了详细的安装方式和步骤&#xff0c;这里咱们使用 docker 进行安装 根据文档上的命令&#xff0c;自己修改如下&#xff1a; docker run \ -u root \ --name jenki…