分布式事务基础理论和解决方案解析

1、什么是事务?

事务可以看成是一次大的活动,它由不同的小活动组成,这些活动要么全部成功,要么全部失败。
(比如一次交易看成是一次大的活动,里面包含两个小的活动:交钱、交货。此时不能只交钱、也不能只交货)

2、什么是本地事务?

本地事务指的是数据库和应用在同一台服务器上,此时我们通常借助数据库本身提供的ACID四大事务特性来解决事务。

3、什么是分布式事务?

随着互联网的发展,软件系统由原来的单体应用转变为分布式应用。如下图所示的阶段演变:
在这里插入图片描述
分布式事务是指在分布式系统下,多个服务之间通过网络远程调用来完成一个事务。
(分布式事务:比如创建订单减库存事务,服务1用来创建订单,服务2是用来减库存的。如果在服务1调用服务2时,服务2宕机了或者网络断开了,就会导致订单创建了而库存没有增加的情况)

4、为什么分布式事务不能直接由数据库的事务特性来管理

我们知道本地事务依赖数据库本身提供的事务特性来实现,因此以下逻辑可以控制本地事务:

begin transaction;
//1.本地数据库操作:张三减少金额    
//2.本地数据库操作:李四增加金额    
commit transation;

但是在分布式环境下,会变成下边这样:

begin transaction;
//1.本地数据库操作:张三减少金额    
//2.远程调用:让李四增加金额    
commit transation;

此时我们可以设想,当远程调用让李四增加金额成功了,由于网络问题远程调用并没有返回,此时本地事务提交失败就回滚了张三减少金额的操作,此时张三和李四的数据就不一致了。

因此在分布式架构的基础上,传统数据库事务就无法使用了,张三和李四的账户不在一个数据库中甚至不在一个应用系统里,实现转账事务需要通过远程调用,由于网络问题就会导致分布式事务问题。

5、分布式事务产生的场景

1. 典型的场景是微服务架构

微服务之间通过远程调用完成事务操作。

比如:订单微服务和库存微服务,下单的同时订单微服务请求库存微服务减库存。

简而言之:跨JVM进程产生分布式事务。
在这里插入图片描述

2. 单体系统访问多个数据库实例

当单体系统需要访问多个数据库(实例)时就会产生分布式事务。

比如:用户信息和订单信息分别在两个MySQL实例存储,用户管理系统删除用户信息,需要分别删除用户信息及用户的订单信息,由于数据分布在不同的数据实例,需要通过不同的数据库链接去操作数据,此时产生分布式事务。

简言之:跨数据库实例产生分布式事务。
在这里插入图片描述

3.多服务访问同一个数据库实例

比如:订单微服务和库存微服务即使访问同一个数据库也会产生分布式事务,原因就是跨JVM进程,两个微服务持有了不同的数据库链接进行数据库操作,此时产生分布式事务。
**在这里插入图片描述**

6、分布式事务基础理论

分布式系统之所以叫分布式,是因为提供服务的各个节点分布在不同机器上,相互之间通过网络交互。不能因为有一点网络问题就导致整个系统无法提供服务,网络因素成为了分布式事务的考量标准之一。因此,分布式事务需要更进一步的理论支持,接下来,我们先来学习一下分布式事务的CAP理论。

在认识分布式事务的控制、解决方案之前需要先学习一些基础理论,通过理论知识指导我们确定分布式事务控制的目标,从而帮助我们理解每个解决方案。

1.理解CAP

CAP是 Consistency、Availability、Partition tolerance三个词语的缩写,分别表示一致性、可用性、分区容忍性。

下面使用电商系统中的一些业务场景来理解 CAP。

如下图,是商品信息管理的执行流程:
在这里插入图片描述
整体执行流程如下:

  1. 商品服务请求主数据库写入商品信息(添加商品、修改商品、删除商品)
  2. 主数据库向商品服务响应写入成功。
  3. 商品服务请求从数据库读取商品信息。

C - Consistency 一致性:

一致性追求的是数据一致性,指所有节点都能访问到最新的数据。允许返回错误、超时,但是不能返回旧数据。(等同于所有节点访问同一份最新的数据副本,需要数据同步完才可供访问 )

(在数据库主从复制下,为了保证上述的数据一致性,当主库的数据被更新时,需要对从数据库加锁,然后进行数据的复制,加锁之后 可能导致某些请求超时)

A - Availability 可用性:

可用性指每次请求都能获取到非错的响应,但是不能保证获取到的是最新数据。

P -Partition tolerance 分区容忍性:

分布式系统的各服务节点形成一个连通的网络,但是因为某些节点出现网络故障断开,导致原来的网络变成了几个网络分区后,此时系统是否还能正确响应客户端的请求。

2. 为什么 CAP 只能三选二

一个分布式系统里面,节点组成的网络本来应该是连通的。然而可能因为一些故障,使得有些节点之间不连通了,整个网络就分成了几块区域。数据就散布在了这些不连通的区域中。这就叫分区。

当你一个数据项只在一个节点中保存,那么分区出现后,和这个节点不连通的部分就访问不到这个数据了。这时分区就是无法容忍的。

提高分区容忍性的办法就是一个数据项复制到多个节点上,那么出现分区之后,这一数据项就可能分布到各个区里。容忍性就提高了。

然而,要把数据复制到多个节点,就会带来一致性的问题,就是多个节点上面的数据可能是不一致的。要保证一致,每次写操作就都要等待全部节点写成功,而这等待又会带来可用性的问题。

总的来说就是,数据存在的节点越多,分区容忍性越高,但要复制更新的数据就越多,一致性就越难保证。为了保证一致性,更新所有节点数据所需要的时间就越长,可用性就会降低。

3. 比 CAP 理论更合适的 BASE 理论

BASE是 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent (最终一致性)三 个短语的缩写。BASE 理论是对 CAP 中 AP 的一一个扩展,通过牺牲强一致性来获得可用性,当出现故障允许部分不可用但要保证核心功能可用,允许数据在一段时间内是不一致的,但最终达到一致状态。满足BASE理论的事务,我们称之为 “柔性事务”

  • 基本可用: 分布式系统在出现故障时,允许损失部分可用功能,保证核心功能可用。如,电商网站交易付款出现问题了,商品依然可以正常浏览。
  • 软状态: 由于不要求强一致性,所以 BASE 允许系统中存在中间状态(也叫软状态),这个状态不影响系统可用性,如订单的"支付中"、“数据同步中”等状态,待数据最终一致后状态改为”成功”状态。
  • 最终一致: 最终一致是指经过一段时间后,所有节点数据都将会达到一致。如订单的"支付中"状态,最终会变为“支付成功”或者"支付失败" ,使订单状态与实际交易结果达成一致,但需要一定时间的延迟、等待。

7、分布式事务解决方案之 2PC (两阶段提交)

  以前面所说的分布式事务理论为基础(CAP + BASE),针对不同的分布式场景业界常见的解决方案有 2PC、TCC、可靠消息最终一致性、最大努力通知这几种。

1. 传统的 2PC 协议

  2PC 即两阶段提交协议,是将整个事务流程分为两个阶段,准备阶段(Prepare phase)、提交阶段(Commit phase)。

2 是指两个阶段,P 是指准备阶段,C 是指提交阶段。

举例:张三和李四好久不见,老友约起聚餐,饭店老板要求先买单,才能出票。这时张三和李四分别抱怨近况不如意,囊中羞涩,都不愿意请客,这时只能 AA。只有张三和李四都付款,老板才能出票安排就餐。但由于张三和李四都是铁公鸡,形成了尴尬的一幕:

准备阶段:老板要求张三付款,张三付款。老板要求李四付款,李四付款。

提交阶段:老板出票,两人拿票纷纷落座就餐。

例子中形成了一个事务,若张三或李四其中一人钱不够,付不了款,店老板都不会给出票,并且会把已收款退回。

整个事务过程由事务管理器和参与者组成,店老板就是事务管理器,张三、李四就是事务参与者,事务管理器(老板)负责决策整个分布式事务的提交和回滚,事务参与者负责自己本地事务的提交和回滚。

那么 2PC 协议具体在计算机中是怎么实现的呢?

在计算机中部分关系数据库如Oracle、MySQL支持两阶段提交协议,如下图:

  1. 准备阶段(Prepare phase):事务管理器给每个参与者发送Prepare消息(预处理准备消息),每个数据库参与者在本地执行事务,并写本地的Undo/Redo日志,此时事务没有提交。(Undo日志是记录修改前的数据,用于数据库回滚,Redo日志是记录修改后的数据,用于提交事务后写入数据文件)
  2. 提交阶段(commit phase):如果事务管理器收到了参与者的执行失败或者超时消息时,直接给每个参与者发送回滚(Rollback)消息;否则,发送提交(Commit)消息;参与者根据事务管理器的指令执行提交或者回滚操作,并释放事务处理过程中使用的锁资源。注意:必须在最后阶段释放锁资源。

下图展示了2PC的两个阶段,分成功和失败两个情况说明:
成功情况:
在这里插入图片描述
失败情况:
在这里插入图片描述

2. XA 方案 - 基于数据库层来实现 2PC

3. Seata 方案 - 基于应用层来实现 2PC

8、分布式事务解决方案之 TCC

1. 什么是 TCC 事务

  TCC 是 Try、Confirm、Cancel 三个词语的缩写,TCC 要求每个分支事务实现三个操作:预处理 Try、确认 Confirm、撤销 Cancel。Try 操作做业务检查及资源预留,Confirm 做业务确认操作,Cancel 实现一个与 Try 相反的操作即回滚操作。TM 首先发起所有的分支事务的 try 操作,任何一个分支事务的 try 操作执行失败,TM 将会发起所有分支事务的 Cancel 操作,若 try 操作全部成功,TM 将会发起所有分支事务的 Confirm 操作,其中 Confirm/Cancel
操作若执行失败,TM会进行重试。
在这里插入图片描述
分支事务失败的情况:
在这里插入图片描述
TCC 分为三个阶段:

  1. Try 阶段是做业务检查(一致性)及资源预留(隔离),此阶段仅是一个初步操作,它和后续的 Confirm 一起才能真正构成一个完整的业务逻辑。
  2. Confirm 阶段是做确认提交,Try 阶段所有分支事务执行成功后开始执行 Confirm。通常情况下,采用 TCC 则认为 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。若Confirm阶段真的出错了,需引入重试机制或人工处理。
  3. Cancel 阶段是在业务执行错误需要回滚的状态下执行分支事务的业务取消,预留资源释放。通常情况下,采用 TCC 则认为 Cancel 阶段也是一定成功的。若 Cancel 阶段真的出错了,需引入重试机制或人工处理。

TM 事务管理器:
TM 事务管理器可以实现为独立的服务,也可以让全局事务发起方充当 TM 的角色,TM 独立出来是为了成为公用组件,是为了考虑系统结构和软件复用。

TM 在发起全局事务时生成全局事务记录,全局事务 ID 贯穿整个分布式事务调用链条,用来记录事务上下文,追踪和记录状态,由于 Confirm 和 cancel 失败需进行重试,因此需要实现为幂等,幂等性是指同一个操作无论请求多少次,其结果都相同。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值