分布式事务学习笔记

MySQL事务

1、 MySQL事务隔离级别

  • 读未提交 (READ UNCOMMITTED) (存在脏读的问题)
  • 读已提交(READ COMMITTED)
  • 可重复读(REPEATABLE READ)
  • 串行化(SERIALIZABLE)
    通过以下 SQL 可以设置当前客户端的事务隔离级别:
    set session transaction isolation level 事务隔离级别;

可重复读(Repeable Read)是 MySQL 默认事务隔离级别

2、并发事务带来的问题

  • 脏写
    一个事务的更新覆盖了另一个事务的更新
  • 脏读(读未提交)
    一个事务修改还没有提交事务,另一个事务读取了未提交的数据
  • 不可重复读(读已提交)
    一个事务读取某些数据,过一段时间再读发现数据变了或者被删除了
  • 幻读
    一个事务按照相同的查询条件重新读取之前读过的数据,此时发现其他事务插入了满足当前事务查询条件的新数据,这种现象叫作幻读。

2.1、脏读

脏读是一个事务可以读到另一个事务还没有提交的数据。

演示执行流程如下:

2.2、不可重复读

不可重复读是指一个事务先后执行同一条 SQL,但两次读取到的数据不同

2.3、 幻读

幻读名如其文,它就像发生了某种幻觉一样,在一个事务中明明没有查到主键为 X 的数据,但主键为 X 的数据就是插入不进去。

3、 MySQL中锁的分类

  • 行锁主要加在索引上,如果对非索引的字段设置条件进行更新,行锁可能会变成表锁。
  • InnoDB的行锁是针对索引加锁,不是针对记录加锁,并且加锁的索引不能失效,否则行锁可
    能会变成表锁。
  • 锁定某一行时,可以使用lock in share mode命令来指定共享锁,使用for update命令来指
    定排他锁,例如下面的SQL语句。
    select * from userinfo where id = 1 for update;

4、 MySQL事务的实现原理 redo log && undo log

MySQL的事务实现离不开Redo Log和Undo Log。从某种程度上说,事务的隔离性是由锁和MVCC机制实现的,原子性和持久性是由Redo Log实现的,一致性是由Undo Log实现的。

4.1、什么是redo log

redo log叫做重做日志,是用来实现事务的持久性。该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log),前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都会存到该日志中。

先写日志,再写磁盘的技术就是 MySQL 里经常说到的 WAL(Write-Ahead Logging) 技术。

4.1.1、Redo Log刷盘规则

在计算机操作系统中,用户空间( user space )下的缓冲区数据一般情况下是无法直接写入磁盘的,中间必须经过操作系统内核空间( kernelspace )缓冲区( OS Buffer )。因此, redo log buffer 写入 redo log file 实际上是先写入 OS Buffer ,然后再通过系统调用 fsync() 将其刷到 redo log file 中。

mysql 支持三种将 redo log buffer 写入 redo log file 的时机。innodb_flush_log_at_trx_commit。

不同的Redo Log刷盘规则,对MySQL数据库性能的影响也不同。

查看刷盘规则:show variables like 'innodb_flush_log_at_trx_commit';

设置刷盘规则:set global innodb_flush_log_at_trx_commit=0;

注意:

当innodb_flush_log_at_trx_commit变量的值设置为0或者2时,插入10万条数据耗费的时间差别不是很大,但是与innodb_flush_log_at_trx_commit变量的值设置为1对比来看,耗时差别较大。需要注意的是,虽然将innodb_flush_log_at_trx_commit变量的值设置为0或者2时,插入数据的性能比较高,但是在系统发生故障时,可能会丢失1s的数据,而这1s内可能会产生大量的数据。也就是说,可能会造成大量数据丢失。

4.2 什么是undo log

undo log是mysql中比较重要的事务日志之一,顾名思义,undo log是一种用于撤销回退的日志,在事务没提交之前,MySQL会先记录更新前的数据到 undo log日志文件里面,当事务回滚时或者数据库崩溃时,可以利用 undo log来进行回退。

4.2.1、undo log的作用

  • 1、提供回滚操作

---修改之前name = 张三 update user set name = "李四" where id = 1;

----此时undo log会记录一条相反的update语句,如下: update user set name = "张三" where id = 1;

如果这个修改出现异常,可以使用undo log日志来实现回滚操作,以保证事务的一致性。

  • 2、提供多版本控制(MVCC)

MVCC,即多版本控制。在MySQL数据库InnoDB存储引擎中,用undo Log来实现多版本并发控制(MVCC)。当读取的某一行被其他事务锁定时,它可以从undo log中分析出该行记录以前的数据版本是怎样的,从而让用户能够读取到当前事务操作之前的数据【快照读】。

快照读:

SQL读取的数据是快照版本【可见版本】,也就是历史版本,不用加锁,普通的SELECT就是快照读。

当前读:

---修改之前name = 张三 update user set name = "李四" where id = 1;

----此时undo log会记录一条相反的update语句,如下: update user set name = "张三" where id = 1; SQL读取的数据是最新版本。通过锁机制来保证读取的数据无法

通过其他事务进行修改UPDATE、DELETE、INSERT、SELECT... LOCK IN SHARE MODE、SELECT ... FOR

UPDATE都是当前读

4.2.2、undo log的工作原理

在更新数据之前,MySQL会提前生成undo log日志,当事务提交的时候,并不会立即删除undo log,因为后面可能需要进行回滚操作,要执行回滚(rollback)操作时,从缓存中读取数据。undo log日志的删除是通过通过后台purge线程进行回收处理的。

4.2.3、 总结

undo log是用来回滚数据的用于保障未提交事务的原子性。

分布式事务

简介:略

1、CAP理论

分布式有三个指标:

这三个指标不可能同时做到,这个结论就是CAP定律。

1.1、 分区容错性

大多数分布式系统都分布在多个子网络。每个子网络就叫做一个区。分区容错的意思是,区间通信可能失败。比如,一台服务器放在中国,另一台服务器放在美国,这就是两个区,它们之间可能无法通信。
结论:

分区容错无法避免,因此可以认为 CAP 的 P 总是成立。CAP 定理告诉我们,剩下的 C 和 A 无法同时做到。

1.2、 一致性

Consistency 中文叫做"一致性"。意思是,写操作之后的读操作,必须返回该值。举例来说,某条记录是 v0,用户向 G1 发起一个写操作,将其改为 v1。

此时用户读G1节点返回v1,就叫做一致性,但是如果读G2节点返回v0就无法满足一致性。

为了让 G2 也能变为 v1,就要在 G1 写操作的时候,让 G1 向 G2 发送一条消息,要求 G2 也改成 v1。

1.3、 可用性

只要收到用户的请求,服务器就必须给出回应。

用户可以选择向 G1 或 G2 发起读操作。不管是哪台服务器,只要收到请求,就必须告诉用户,到底是 v0 还是 v1,否则就不

满足可用性。

1.4、 一致性和可用性的矛盾:

如果保证 G2 的一致性,那么 G1 必须在写操作时,锁定 G2 的读操作和写操作。只有数据同步后,才能重新开放读写。锁定期间,G2 不能读写,没有可用性。如果保证 G2 的可用性,那么势必不能锁定 G2,所以一致性不成立。

1.5、 一致性和可用性如何选择

1、一致性CP

放弃可用性,追求系统的一致性和分区容忍性。这种组合方式对于数据的一致性要求比较高,追求的是强一致性。特别是涉及到重要的数据,就比如钱,商品数量,商品价格。
2、 可用性AP

放弃一致性,追求系统的可用性和分区容忍性。这是实际工作中,大部分分布式系统在架构设计时的选择。

分布式事物解决方案

1、强一致性分布式事务之2PC模型

两阶段提交又称2PC,2PC是一个强一致、中心化的原子提交协议,这里所说的中心化是指协议中有两类节点:是中心化协调者节点和N个参与者节点。

两个阶段

  • 投票阶段
  • 提交/执行阶段

例子:

A组织B、C、D去爬山,投票如果有不同意的就不去

2PC缺点

2、XA方案

2PC的传统方案是在数据库层面实现的。如Oracle、MySQL都支持2PC协议,为了统一标准减少行业内不必要的对接成本,需要制定标准化的处理模型及接口标准,国际开放标准组织Open Group定义分布式事务处理模型DTP(Distributed Transaction Processing Reference Model)

DTP模型定义角色

  • AP(Application Program):
    即应用程序,可以理解为使用DTP分布式事务的程序。
  • RM(Resource Manager):资源管理器:
    可以理解为事务的参与者,一般情况下是指一个数据库实例,通过资源管理器对该数据库进行控制,资源管理器控制着分支事务。
  • TM(Transaction Manager):事务管理器:
    负责协调和管理事务,事务管理器控制着全局事务,管理事务生命周期,并协调各个RM。全局事务是指分布式事务处理环境中,需要操作多个数据库共同完成一个工作,这个工作即是一个全局事务。

DTP模型定义TM和RM之间通讯的接口规范叫XA,简单理解为数据库提供的2PC接口协议,基于数据库的XA协议来实现2PC又称为XA方案。

3、Seata实现

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 为用户提供了 AT、TCC、SAGA和 XA 事务模式,为用户打造一站式的分布式解决方案。

3.1、全局事务与分支事务的关系图

与传统2PC的模型类似,Seata定义了三个组件来协调分布式事务的处理过程

具体流程:

  • Transaction Coordinator(TC):事务协调器,它是独立的中间件,需要独立部署运行,它维护全局事务的运行状态,接收TM指令发起全局事务的提交与回滚,负责与RM通信协调各个分支事务的提交或回滚。
  • Transaction Manager(TM):事务管理器,TM需要嵌入应用程序中工作,它负责开启一个全局事务,并最终向TC发起全局提交或全局回滚的指令。
  • Resource Manager(RM):控制分支事务,负责分支注册、状态汇报,并接收事务协调器TC的指令,驱动分支(本地)事务的提交和回滚。

3.2、Seata实现2PC与传统2PC的差别

  • 架构层次方面,传统2PC方案的RM实际上是在数据库层,RM本质上就是数据库自身,通过XA协议实现,而Seata的RM是以jar包的形式作为中间件层部署在应用程序的这一侧的。
  • 性能层面:两阶段提交方面,传统2PC无论第二阶段的决议是commit还是rollbcak,事务性资源的锁都要保持到Phase2完成才释放。而Seata的做法是在Phase1就将本地事务提交,这样就可以省去Phase2持锁的时间,整体提高效率。

3.3、Seata实现XA要点

1、全局事务开始使用GlobalTransactional标识。

2、每个本地事务方案仍然使用@Transactional标识。

3、每个数据都需要创建undo_log表,此表是Seata保证本地事务一致性的关键。

4、将@GlobalTransactional注解标注在全局事务发起的Service实现方法上,开启全局事务 :GlobalTransactionalInterceptor会拦截@GlobalTransactional注解的方法,生成全局事务ID(XID),XID会在整个分布式事务中传递。在远程调用时,spring-cloud-alibaba-seata会拦截Feign调用将XID传递到下游服务。

3.4、结论:

传统2PC(基于数据库XA协议)和Seata实现2PC的两种2PC方案,由于Seata的零入侵并且解决了传统2PC长期锁资源的问题,所以推荐采用Seata实现2PC。

4、BASE理论

BASE理论是对CAP理论的延伸。

4.1、为何会出现BASE理论

CAP 理论表明,对于一个分布式系统而言,它是无法同时满足Consistency(强一致性)、Availability(可用性) 和 Partitiontolerance(分区容忍性) 这三个条件的,最多只能满足其中两个。

理由:

为了用户体验,先选可用性。

放弃了一致性的系统又失去了存在的意义。

4.2、什么是BASE理论:

BASE 是 Basically Available(基本可用) 、Soft-state(软状态)和 Eventually Consistent(最终一致性) 三个短语的缩写。

4.3、核心思想:

既是无法做到强一致性(Strong consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。

4.4、BASE理论的三要素

4.4.1、基本可用(Basically Available)

基本可用是指分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。允许损失部分可用性。但是,这绝不等价于系统不可用。

4.4.2、软状态(Soft State)

软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。即允许系统在多个不同节点的数据副本存在数据延时。

注:

用户在商城下单时,因网络超时等因素,订单处于"支付中"的状态,待数据最终一致后状态将变更为"关闭"或"成功"状态。

4.4.3、最终一致性(Eventual Consistency)

最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。弱一致性和强一致性相反,最终一致性是弱一致性的一种特殊情况。

4.5、分布式一致性的 3 种级别:

  • 强一致性 :系统写入了什么,读出来的就是什么。
  • 弱一致性 :不一定可以读取到最新写入的值,也不保证多少时间之后读取到的数据是最新的,只是会尽量保证某个时刻达到数据一致的状态。
  • 最终一致性 :弱一致性的升级版,系统会保证在一定时间内达到数据一致的状态。
    业界比较推崇是最终一致性级别,但是某些对数据一致要求十分严格的场景比如银行转账还是要保证强一致性。

4.6、总结

ACID 是数据库事务完整性的理论,CAP 是分布式系统设计理论,

BASE 是 CAP 理论中 AP 方案的延伸。符合Base理论的事务可以称为柔性事务。

5、最终一致性分布式事务

强一致性分布式事务解决方案要求参与事务的各个节点的数据时刻保持一致,查询任意节点的数据都能得到最新的数据结果。这就导致在分布式场景,尤其是高并发场景下,系统的性能受到影响。而最终一致性分布式事务解决方案并不要求参与事务的各节点数据时刻保持一致,允许其存在中间状态,只要一段时间后,能够达到数据的最终一致状态即可。

5.1、典型方案

为了解决分布式、高并发场景下系统的性能问题,业界基于Base理论提出了最终一致性分布式事务解决方案。

  • TCC解决方案。
  • 可靠消息最终一致性解决方案。
  • 最大努力通知型解决方案。

5.2、适用场景

每个服务都存在中间状态,服务与服务之间不必保持强一致性,允许在某个时刻查询出来的数据存在短暂的不一致性,经过一段时间后,各个服务之间的数据能够达到最终一致性。这样,不仅各个服务的数据达到了最终一致性,还极大地提高了系统的整体性能并降低了分布式事务执行过程中出错的概率。

5.3、优缺点

5.3.1、最终一致性分布式事务解决方案的优点:

  • 性能比较高,这是因为最终一致性分布式事务解决方案不要求数据时刻保持一致,不会因长时间持有事务占用的资源而消耗过多的性能。
  • 具备可用性。
  • 适合高并发场景。

5.3.2、最终一致性分布式事务解决方案的缺点:

  • 因为数据存在短暂的不一致,所以在某个时刻查询出的数据状态可能会不一致。
  • 对于事务一致性要求特别高的场景不太适用。

5.4、最终一致性分布式事务解决方案_TCC是什么

TCC(Try-Confirm-Cancel)又称补偿事务。

TCC核心思想

TCC分布式事务最核心的思想就是在应用层将一个完整的事务操作分为三个阶段。在某种程度上讲,TCC是一种资源,实现了Try、Confirm、Cancel三个操作接口。

  • Try阶段
    Try阶段是准备执行业务的阶段,在这个阶段尝试执行业务。
    1、完成所有的业务检查,确保数据的一致性。
    2、预留必要的业务资源,确保数据的隔离性。
  • Confirm阶段
    Confirm阶段是确认执行业务的阶段,在这个阶段确认执行的业务。
    1、真正地执行业务。
    2、不做任何业务逻辑检查,直接将数据持久化到数据库。
    3、直接Try阶段预留的业务资源。
  • Cancel阶段
    Cancel阶段取消执行业务。
    1、释放Try阶段预留的业务资源。
    2、将数据库中的数据恢复到最初的状态。

TCC核心组成

5.5、什么是可靠消息最终一致性事务

可靠消息最终一致性的基本原理是事务发起方(消息发送者)执行本地事务成功后发出一条消息,事务参与方(消息消费者)接收到事务发起方发送过来的消息,并成功执行本地事务。事务发起方和

事务参与方最终的数据能够达到一致的状态。

1、1两种实现方式

  • 基于本地消息表(vhr有类似实现)
  • 基于支持分布式事务的消息中间件,如RocketMQ

1.2 基本原理

  • 事务发起方一定能够将消息成功发送出去。
  • 事务参与方一定能够成功接收到消息。

1.3、本地消息表

本地消息表模式的核心是通过本地事务保证数据业务操作和消息的一致性,然后通过定时任务发送给消费方或者中间加一层MQ的方式,保障数据最终一致性。

1.3.1、库表设计

1、订单微服务出库本地消息表

2、基础功能

3、流程

4、Task微服务的任务

5、定时任务的作用:

1.4 、RocketMQ事务消息

支持事务消息的消息中间件

RocketMQ 4.3版之后引入了完整的事务消息机制,其内部实现了完整的本地消息表逻辑,使用RocketMQ实现可靠消息分布式事务就不用用户再实现本地消息表的逻辑了,极大地减轻了开发工作量

2、最终一致性分布式事务解决方案_最大努力通知型分布式事务

适用于时间敏感度低的业务。

最大努力通知型( Best-effort delivery)是最简单的一种柔性事务。

最典型的使用场景就是支付成功后,支付平台异步通知商户支付结果。并且事务被动方的处理结果不会影响主动方的处理结果。 典型的使用场景:如银行通知、商户通知等。

  • 有一定的消息重复通知机制:接收通知方有可能无法接收到通知,一定要具有重复通知的机制。
  • 消息校对机制:在重复通知仍然没有通知到对方,可由接收通知方主动查询信息。
相关推荐
憨子周38 分钟前
2M的带宽怎么怎么设置tcp滑动窗口以及连接池
java·网络·网络协议·tcp/ip
霖雨2 小时前
使用Visual Studio Code 快速新建Net项目
java·ide·windows·vscode·编辑器
SRY122404192 小时前
javaSE面试题
java·开发语言·面试
Fiercezm3 小时前
JUC学习
java
无尽的大道3 小时前
Java 泛型详解:参数化类型的强大之处
java·开发语言
ZIM学编程3 小时前
Java基础Day-Sixteen
java·开发语言·windows
我不是星海3 小时前
1.集合体系补充(1)
java·数据结构
P.H. Infinity3 小时前
【RabbitMQ】07-业务幂等处理
java·rabbitmq·java-rabbitmq
爱吃土豆的程序员3 小时前
java XMLStreamConstants.CDATA 无法识别 <![CDATA[]]>
xml·java·cdata
2401_857610034 小时前
多维视角下的知识管理:Spring Boot应用
java·spring boot·后端