当前位置: 移动技术网 > IT编程>数据库>Mysql > 分布式事务

分布式事务

2020年07月23日  | 移动技术网IT编程  | 我要评论

一、什么是分布式事务

1、本地事务

本地事务只的是本地数据库事务;例如mysql 可以通过begin或者start transaction开启一个事务,在事务提交之前操作如果中间某个原子操作失败了会触发回滚,通过commit提交事务。如果不显式的开启事务,mysql会默认开启一个事务来执行sql操作。

事务的四个特性:原子性、一致性、隔离性、持久性

2、undo和redo

本地事务通过undo log来进行回滚操作,通过redo log保证事务提交前宕机了事务的恢复;

数据在写入磁盘之前都会缓存在内存中,在事务提交之前会先把数据写入到undo和redo log中,提交的时候才真正将数据写入到磁盘中。

假设有A=1;B=2两条数据需要在一个事务里进行修改

1、开始事务
2、undo A=1;
3、修改A=2;
4、undo B=2;
5、修改B=3;
6、将undo log写入到磁盘
7、将A、B新的数据写入到磁盘
8、提交事务;
19、事务提交成功删除undo 日志

【1】如何保证事务的持久性?

在提交事务之前已将将数据写入到磁盘中了。

【2】如何保证数据的一致性、原子性?

如果在7步操作的时候发生异常,例如A写磁盘成功,B写磁盘失败,这个时候可以根据undo log进行回滚操作,undo log是都写入到磁盘中了;如果7之前发生异常了磁盘中A、B的值还是原来的值。

【3】什么时候需要undo,为什么需要undo?

例如在7步操作的时候A写磁盘成功了,要写B到磁盘的时候异常了,这个时候就需要根据undo 进行回滚。

【4】什么时候需要redo,为什么需要redo?

在事务中将数据落到磁盘是一个重量级的IO操作,因为是随机写入,undo log写入磁盘是顺序写入是一个快速的轻量级的IO操作;因此通过在事务中记录一个redo log来替代数据写入磁盘的操作。

在事务中记录redo减少了io的次数,因为是将一堆操作日志顺序写入磁盘文件只有一次io操作,比起数据写入磁盘多个IO操作有明显提升。

1、开始事务
2、undo A=1 to undo buffer;
3、修改A=2;
4、redo A=2 to redo buffer
5、undo B=2;
6、修改B=3;
7、redo B=3 to redo buffer
8、将undo、redo log写入到磁盘
9、提交事务;
...
10、错峰后数据写入磁盘
11、数据写入磁盘后删除undo、redo日志

【5】为什么要将undo log写入到redo log?

3、分布式事务

产生分布式事务的原因?

跨服务:服务拆分后,服务与服务之间通过rpc进行调用,不在一个服务器上;单机的事务失效。

在这里插入图片描述

跨库:分库分表后需要操作不同的数据库,不同的数据库之间事务不支持

在这里插入图片描述

二、解决分布式事务的思路

1、CAP理论

在这里插入图片描述

C (consistency):一致性,指的是写操作后的读操作必须返回写操作的值。

A (availablity):可用性,可用性指的是数据能否及时响应返回,而不是指的系统可用。即服务器收到请求后必须给出返回不论对错。

P(partition):分区容错性,分区容错性是一个分布式系统的基本能力,指的是区间通信可能失败,例如一台服务器在北京,一台在上海可能网络通信失败。尽管网络或者消息失败,系统依然按照预期的进行执行。

为甚么一致性和可用性不可兼得?

在这里插入图片描述

例如对于只从复制,读写分离的场景,主从之间同步必然有一定的延时,主写操作完后,如果立马从从机读取读取到的不一定是写后的数据,也就是有不一致;如果需要从机读到的数据和主保持一致那么必然需要等待主从同步完成,满足不了立马返回的可用性的要求。

通常是选择AP牺牲C

问题一、怎么同时满足CA?

只有单体的架构才能同时满足CA

问题二、怎么满足CP?

通过zookeeper来保证各个节点数据的一致性,但是在数据同步的过程中不可用,牺牲了可用性。

问题三、怎么保证AP?

对可用性要求较高的场景,例如Eureka,必须保证注册中心随时可用,不然拉取不到数据就不能提供服务

2、BASE理论

基本可用:basic available

软状态:soft state,允许存在中间

最终一致:eventually consistency

3、分阶段提交

open group组织定义DTP模型;

DTP模型包含以下几个角色:

AP : 微服务应用程序

TM : 事务管理者

RM :资源管理者-数据库

CRM : 通信资源管理器,是TM和RM之间的通信中间件

分布式全局事务可以拆分成多个本地事务,但是需要一个全局的协调者来确保各个本地事务之间处理状态一致,同时成功或者同时失败,失败的话需要将成功的进行回滚。因此各个本地事务之间要通信的话就必须要有统一的标准,即open group定义了一套标准的XA接口,包括事务的开始、提交、回滚等,各个数据库产商都需要实现这些接口。

【1】两阶段提交协议

在这里插入图片描述

准备阶段:协调者向参与者发送执行请求,参与者记录undo、redo日志,并执行请求但不提交,如果成功则向协调者发送同意如果失败则发送终止,协调者根据所有参与者反馈的结果决定是提交还是回滚。

提交阶段:如果所有参与者都同意,则协调者发送提交请求,所有参与者都提交成功,则完成此次事务,如果存在参与者提交失败,则协调者发送回滚请求回滚其他参与者完成的事务。整个分布式事务失败。

存在的问题:1、存在协调者单点问题;2、同时如果参与者在提交阶段发送完成消息给协调者时出现网络问题,那么协调者会回滚其他参与者完成的事情,造成数据的不一致;3、 执行过程中,所有参与节点都是事务阻塞型的,一直占用锁资源,导致并发量很低 。

如果存在很多个参与者,只有当协调者收到所有的参与者的yes回复后才能提交,因此所有节点是阻塞的

【2】三阶段提交协议

在这里插入图片描述

三阶段比二阶段多了一个预备阶段,引入超时机制,在预备阶段就给出事务是否可以执行的判断,减少阻塞,提高并发; 相对于2PC,3PC主要解决的单点故障问题,并减少阻塞 ,因为一旦参与者无法及时收到来自协调者的信息之后,他会默认执行commit。而不会一直持有事务资源并处于阻塞状态。但是这种机制也会导致数据一致性问题,因为,由于网络原因,协调者发送的abort响应没有及时被参与者接收到,那么参与者在等待超时之后执行了commit操作。这样就和其他接到abort命令并执行回滚的参与者之间存在数据不一致的情况。

与两阶段提交不同的是,三阶段提交有两个改动点。

1、引入超时机制。同时在协调者和参与者中都引入超时机制。
2、在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。

也就是说,除了引入超时机制之外,3PC把2PC的准备阶段再次一分为二,这样三阶段提交就有CanCommit、PreCommit、DoCommit三个阶段。在preCommit阶段会记录undo、redo log但不真正提交。

4、TCC

在这里插入图片描述

【1】介绍

TCC是try-confirm-cancel的缩写,本质是一种补偿的机制是为了解决2pc模型中的资源锁定和阻塞问题提出的一种模型。

一阶段:

try : 检测和预留资源

二阶段:

confirm :执行提交,要求try成功confirm必须成功

cancel :try失败,掉cancel进行回滚回滚

TCC模式的所有参与者RM都需要实现try、confirm、cancel三个方法;TM协调者负责编排参与者以及提交工作,TM调用RM提供的三个方法来进行一阶段的try、二阶段的confirm和cancel操作。因为try阶段已经冻结了资源,那么confirm阶段可以与try阶段错开实现错峰提交。

【2】实例

在这里插入图片描述

例如要在A账户下扣30,try阶段需要检查余额是否大于30,大于则从余额中冻结30元,通过记一个冻结字段实现;confirm阶段从余额中扣除30元,并将冻结的金额清0;cancel阶段将冻结的余额清0。

在这里插入图片描述

TCC的三个方法都需要保证幂等性,即需要做防重复处理,无论多少次请求只要入参一样返回结果都也一样。因为假如confirm阶段RM服务执行或者网络超时了,TM进行重试,如果不支持幂等那么可能会导致超扣或者超发的情况。

【3】规范

TCC三个方法设计上应该满足如下几个规范:

幂等 :及防重复

防并发控制 :防并发

防空回滚控制 :

防悬挂控制

5、可靠消息服务

【1】原理

源于ebay,思路是将远程分布式事务拆分成一系列本地事务,通过可靠消息中间件保证事务的一致性。只要将消息成功的发送到了MQ那么事务的发起者服务A就认为这个分布式事务是成功的。其他参与者服务B通过重试补偿的方法来保证与它相关的事务执行成功。

在这里插入图片描述

主要包括事务的发起者A,和事务的其他参与者B;

服务A执行本地事务;

服务A通过MQ将消息发送给服务B;

服务B从MQ中收到服务A的消息后,执行本地事务;

【2】本地消息表

为了避免消息发送失败,将消息保存到本地数据库中,实现时有简化版和解耦版两种

简化版

在这里插入图片描述

在发送消息到MQ前,先将消息持久化到本地数据库表中;

实例:外围系统调用批量发券的场景;外围先将消息发送给MQ,spes收到消息后先记录到同步请求表中,通过定时任务从表中捞取数据进行发券处理,成功后将返券的消息先记录到响应表中,然后通过定时任务从响应表中捞取数据再通过MQ发送给外围系统。

解耦版

在这里插入图片描述

需要一个独立的可靠消息服务模块,来对消息完成持久化、发送、确认、失败重试等操作

【3】优点和缺点

优点:

业务相对简单,不需要编写TCC的三个方法;

因为是多个本地事务,资源锁定的周期短,没有阻塞的问题。

缺点:

有代码侵入

依赖消息中间件MQ的可靠性

发布者可以引起回滚,但是参与者不能引起事务回滚

时效性差

6、FMT模式

阿里巴巴seta分布式事务模式演进

在这里插入图片描述

【1】介绍

FMT模式是framwork-management-transaction的缩写,是一种对业务代码没有侵入的实现方式,解决了TCC模式中代码侵入,编码复杂的问题。不需要编写复杂的TCC方法,全由框架实现。

TC:事务协调者:维护全局和分支事务的状态;驱动全局事务的提交和回滚。

TM:事务管理者,定义全局事务的范围,开启全局事务,提交和回滚事务。

RM:资源管理者,与TC沟通注册并报告分支事务的状态。

使用过程包括如下几个点:

a) 搭建TC服务器

b) 在微服务中引入TM\RM组件

c) 定义全局事务的范围

d) 告知所有的参与者TC的地址

【2】阶段介绍

在这里插入图片描述

在FMT模式下业务方只需要关注自身sql的实现,事务的维护由框架实现。

一阶段:

a) 解析sql语义、表元素数据提取

在这里插入图片描述

遍历sql中的语法树,解析语法树antlr,提取语法树中的语句字段,如表名、查询条件、更新字段、类型等。用于后面自动生成confirm、cancel的语句进行提交和取消。

b) 保存undo、redo日志和行锁

在这里插入图片描述

为什么要保存行锁?进行FMT并发事务控制

在这里插入图片描述

二阶段:

框架自动生成提交或者回滚操作

在这里插入图片描述

如果是二阶段提交,则删除中间的数据包括undo log、redo log、行锁

如果是二阶段回滚:通过undo log或者逆向sql进行数据还原,并删除中间的数

在这里插入图片描述

【3】同库模式

在这里插入图片描述

本文地址:https://blog.csdn.net/khuangliang/article/details/107509054

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网