认识分布式事务

  • 什么是事务

事务基本理论:

1、从数据库的角度(对数据库来说): 一个 SQL 语句就是一个事务

2、从业务角度: 一个程序实现单元就是一个事务(一条或多个 SQL 组成)

事务特性:ACID 事务特性

1、原子性: 要么都成功,要么都失败

2、一致性: 事务开启之前对其他线程可见的状态,中间状态不可见,事务结束之后才可见。

3、隔离性: 事务与事务之间隔离的 (底层使用锁)

4、持久性: 把数据存储在磁盘

开发业务: 一般情况下,都使用本地事务(没有解决分布式事务)

如下:本地事务,单机事务 一个事务单元

认识分布式事务

特点: 应用程序操作的是单一的数据源,让多个操作是一个原子性操作。

思考问题

项目都使用分布式架构的模式,数据一致性处理非常困难???

1、网络抖动

2、网络延迟

3、服务宕机(无法避免)

4、机器宕机

5、程序崩溃

6、异常异常

………………….

以上问题是必然会发生的,因此解决数据一致性问题才会如此困难? ---- 在处理数据一致

性的问题上面,必须有所取舍 ----

强一致性(基于数据库) ----- CAP 理论(分布式)----- Base 理论(最终一致性)

  • CAP

在当前的软件架构模式下,有状态服务部署(分布式部署模式下),无法同时保证可用性,

和一致性,必须有所取舍。

如果我们保证一致性,会存在分区的问题。

如果追求一致性:可让数据完成同步后,大家在去读去数据,损失一部分性能,换取一致性。

如果追求可用性:可以采用异步模式同步数据,只有主机进行读操作,从机负责备份,监控主机,切换master,切换这一瞬间,从机是没有主机部分数据的,因此会存在数据的丢失。

在互联网项目,追求性能上提升,因此选择可用性,提升项目性能。但是选择可用性后,数据一致性会存在问题。如何解决呢??

  • Base 理论

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

基本可用(Basically Available)指分布式系统在出现不可预知故障的时候,允许损失部分可用性。

软状态( Soft State)指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性。

最终一致( Eventual Consistency)强调的是所有的数据更新操作,在经过一段时间的同步之后,最终都能够达到一个一致的状态

解决方案:

最大努力通知(非可靠消息、定期校对)

可靠消息最终一致性(异步确保

TCC(两阶段型、补偿型)

  • 分布式事务场景

分布事务基本定义:

当下互联网绝大部分公司都进行了数据库拆分和服务化(SOA),微服务。在这种情况下,完成某一个业务功能可能需要横跨多个服务,操作多个数据库。

这就涉及到到了分布式事务,用需要操作的资源位于多个资源服务器上,而应用需要保证对于多个资源服务器的数据的操作,要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同资源服务器的数据一致性

从分布式架构层面对分布式事务进行分析:

认识分布式事务

注意: 以上架构把一个事务单元拆分为多个子事务(微服务架构拆分),以上每一个子事务都属于一个业务动作,在业务需求来说,要求这些业务动作要么都成功,要么都失败。也就是说要求这 4 个事务,要么都成功,要么都失败。

总结: 所谓的分布式事务,其实就是保证多个子事务要么都成功,要么都失败;

问: 以下的场景,是否属于分布式事务的场景???

场景 1:一个应用程序操作多个库(redis,mysql,es,mq………..)

认识分布式事务

以上也属于分布式事务场景,解决 Redis,mysql 数据一致性的问题。使用本地事务,只能控制 MySQL 数据一致性 ,不能控制 Redis 数据一致性。因此 Redis mysql 如果存在业务的关联性,必须保证 Redis,mysql 数据一致性。

场景 2: 应用程序操作的多个数据源,是否属于分布式事务?

认识分布式事务

以上的操作方式,是操作多个数据源(事务本质:数据库的事务),因此 datasource1,datasource2

属于不同的事务,这个 2 个事务相互没有感知,因此这 2 个事务属于隔离的状态,是属于不同进程的事务。因此这个属于分布式事务。

如何解决分布式事务?

感知:

1、感知不同服务事务状态,如果每一个服务事务都准备好了,统一通知大家一起提交。

2、业务补偿机制

  • 分布式事务规范
  1. X/OPEN 事务模型

1)应用程序(Application Program : AP): 定义事务边界(事务开始,结束)--- @Transactional @分布式事务注解

2)资源管理器 (Resource Manager: RM):任何用来存储数据的服务

3)事务管理器(Transaction Manager : TM): 监控事务进度,负责事务提交,回滚 ---TransactionManager

4)通信资源管理(Communcation Resource Manager : CRM)

5) 通信协议 (负责事务模型之间的通信协议)

认识分布式事务

X/open 组织把分布式事务处理模型抽象成了上图所示:AP,TM,RM 三者之间关系。

分布式模式下: 微服务架构:链式调用 --- 存在如下的分布式事务模型 --- 全局事务树模

TM: 存在形式是什么???

1)jar ----- 和应用程序集成在一起

2)服务形式 --- 第三方单独部署

2. Xa接口规范

认识分布式事务

XA:定义了TM和RM交互接口规范【事务注册、提交、回滚、事务结束.....】

XA标准:存储的数据的服务都开放了支持分布式事务接口规范 XA(MYSQL 、ORACLE)

TM 事务管理器也必须遵循XA的规范来调用事务控制器接口

x/open 组织制定 TM/RM 接口交互规范,用来处理分布式事务。

1)xa_reg 注册事务

2)xa_start 开启事务

3)xa_close 关闭事务

……………………………………………………………..

思考: 如何没有接口规范,会发生什么???

RM(存储数据的服务)

1)MYSQL

2)Oracle

3)SQL server

4)mq

TM (事务管理器)-- 厂商开发了很多事务管理器

XA 接口规范制定后:

Mysql5.7 实现 xa 接口规范,支持分布式事务

Rocketmq 集成 xa 接口规范

数据库分布式支持:

认识分布式事务

3、2pc

两阶段提交协议(Two Phase Commit),XA 规范对其进行了优化。而从字面意思来理解,Two Phase Commit,就是将提交(commit)过程划分为 2 个阶段(Phase):


认识分布式事务

应用程序: 只需要定义事务边界即可,一切事务执行,提交,回滚都交给 TM存在问题:

1、阻塞问题: TM 宕机,事务已经执行(上锁),一直处于阻塞状态,无法释放。

2、数据一致性问题

Commit 阶段,RM1 已经提交,RM1 由于网络的原因,没有送达提交信息,出现RM1,RM2 数据不一致的问题。

4、3pc

三阶段提交(3PC)[Three-phase commit],是二阶段提交(2PC)的改进版本。与两阶段提交不同的是,三阶段提交有两个改动点

- 引入超时机制。同时在协调者和参与者中都引入超时机制。

- 在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。也就是说,除了引入超时机制之外,3PC 把 2PC 的准备阶段再次一分为二,这样三阶段提交就有 CanCommit、PreCommit、DoCommit 三个阶段

认识分布式事务

CanCommit阶段

3PC的CanCommit阶段其实和2PC的准备阶段很像。协调者向参与者发送commit请求,参与者如果可以提交就返回Yes响应,否则返回No响应。

  • 事务询问

    协调者向参与者发送CanCommit请求。询问是否可以执行事务提交操作。然后开始等待参与者的响应。

  • 响应反馈 参与者接到CanCommit请求之后,正常情况下,如果其自身认为可以顺利执行事务,则返回Yes响应,并进入预备状态。否则反馈No

PreCommit阶段

协调者根据参与者的反应情况来决定是否可以记性事务的PreCommit操作。根据响应情况,有以下两种可能。

假如协调者从所有的参与者获得的反馈都是Yes响应,那么就会执行事务的预执行。

  • 发送预提交请求 协调者向参与者发送PreCommit请求,并进入Prepared阶段。

  • 事务预提交 参与者接收到PreCommit请求后,会执行事务操作,并将undo和redo信息记录到事务日志中。

  • 响应反馈 如果参与者成功的执行了事务操作,则返回ACK响应,同时开始等待最终指令。

doCommit阶段

该阶段进行真正的事务提交,也可以分为以下两种情况。

执行提交

  • 发送提交请求 协调接收到参与者发送的ACK响应,那么他将从预提交状态进入到提交状态。并向所有参与者发送doCommit请求。

  • 事务提交 参与者接收到doCommit请求之后,执行正式的事务提交。并在完成事务提交之后释放所有事务资源。

  • 响应反馈 事务提交完之后,向协调者发送Ack响应。

  • 完成事务 协调者接收到所有参与者的ack响应之后,完成事务。

中断事务 协调者没有接收到参与者发送的ACK响应(可能是接受者发送的不是ACK响应,也可能响应超时),那么就会执行中断事务。

  • 发送中断请求 协调者向所有参与者发送abort请求

  • 事务回滚 参与者接收到abort请求之后,利用其在阶段二记录的undo信息来执行事务的回滚操作,并在完成回滚之后释放所有的事务资源。

  • 反馈结果 参与者完成事务回滚之后,向协调者发送ACK消息

  • 中断事务 协调者接收到参与者反馈的ACK消息之后,执行事务的中断。

在doCommit阶段,如果参与者无法及时接收到来自协调者的doCommit或者rebort请求时,会在等待超时之后,会继续进行事务的提交。(其实这个应该是基于概率来决定的,当进入第三阶段时,说明参与者在第二阶段已经收到了PreCommit请求,那么协调者产生PreCommit请求的前提条件是他在第二阶段开始之前,收到所有参与者的CanCommit响应都是Yes。(一旦参与者收到了PreCommit,意味他知道大家其实都同意修改了)所以,一句话概括就是,当进入第三阶段时,由于网络超时等原因,虽然参与者没有收到commit或者abort响应,但是他有理由相信:成功提交的几率很大。 )

2PC与3PC的区别

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


分布式事务解决方案


分享到:


相關文章: