分布式事务理论篇

简介

我们先来说说什么是分布式事物,我们都知道,数据库事务的几个特性:原子性(Atomicity )、一致性( Consistency )、隔离性或独立性( Isolation)和持久性(Durabilily),简称就是ACID。如果一组处理步骤或者全部发生或者一步也不执行,我们称该组处理步骤为一个事务。
从广义上来看,分布式事务其实也是事务,只是由于业务上的定义以及微服务架构设计的问题,所以需要在多个服务之间保证业务的事务性,也就是 ACID 四个特性;从单机的数据库事务变成分布式事务时,原有单机中相对可靠的方法调用以及进程间通信方式已经没有办法使用,同时由于网络通信经常是不稳定的,所以服务之间信息的传递会出现障碍,而导致各个微服务之间执行不一致而导致数据不一致问题。总结起来分布式事务也就是跨越多个服务的保证数据一致性。

分布式理论

CAP定理

CAP定理是由加州大学伯克利分校Eric Brewer教授提出来的,他指出WEB服务无法同时满足一下3个属性:
指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),最多只能同时三个特性中的两个,三者不可兼得。

一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。
可用性(A):负载过大后,系统是否还能响应客户端的读写请求,响应指的是在正常时间内处理完请求。
比如原来qps(每秒访问量)是1000,现在涨到10000,依然能正常访问。
分区容忍性(P):即分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性或可用性的服务。
下图中分区容错在分布式系统中是不可或缺的,那么C(一致性)和A(可用性)
在这里插入图片描述
在这里插入图片描述

BASE理论

		BASE理论是对CAP中的一致性和可用性进行一个权衡的结果

在这里插入图片描述
BASE 是 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent (最终一致性)三个短语的缩 写。BASE理论是对CAP中AP的一个扩展
(1)基本可用
指分布式系统在出现故障的时候,保证核心可用,允许损失部分可用性。例如,电商在做促销时,为了保证购物系统的稳定性,部分消费者可能会被引导到一个降级的页面。
(2)软状态
指允许系统中的数据存在中间状态,并认为该中间状态不会影响系统整体可用性,即允许系统不同节点的数据副本之间进行同步的过程存在时延。就好比是使用支付宝的时候,会出现支付中、数据同步中等状态,这时候就叫做软状态。但是最终会显示支付成功。
(3)最终一致性
最终一致性强调的是系统中的数据副本,在经过一段时间的同步后,最终能达到一致的状态。如订单的"支付中"状态,最终会变 为“支付成功”或者"支付失败",使订单状态与实际交易结果达成一致,但需要一定时间的延迟、等待。
总体来说BASE理论面向的是大型高可用、可扩展的分布式系统。与传统ACID特性相反,不同于ACID的强一致性模型,BASE提出通过牺牲强一致性来获得可用性,并允许数据段时间内的不一致,但是最终达到一致状态
有了以上理论之后,我们来看一下分布式事务的问题。

分布式解决方案

2PC

2PC(Two-Phase Commit 二阶段提交)
二阶段提交,是指将事务提交分成两个部分:准备阶段和提交阶段。事务的发起者称之为协调者,事务的执行者称为参与者
在这里插入图片描述
在这里插入图片描述

1.阶段一:准备阶段
参与者向协调者注册并发送groupId
参与者执行事务操作,将Undo和Redo放入事务日志中(但是不提交)
如果参与者执行成功就返回YES(可以提交事务),失败NO(不能提交事务)
2.阶段二:提交阶段
此阶段分两种情况:所有参与者均返回YES,有任何一个参与者返回NO
所有参与者均反馈YES时,即提交事务。
任何一个参与者反馈NO时,即中断事务。
提交事务:(所有参与者均反馈YES)
  1、协调者向所有参与者发出正式提交事务的请求(即Commit请求)。
  2、参与者执行Commit请求,并释放整个事务期间占用的资源。
  3、各参与者向协调者反馈Ack完成的消息。
  4、协调者收到所有参与者反馈的Ack消息后,即完成事务提交。

中断事务:(任何一个参与者反馈NO)
  1、协调者向所有参与者发出回滚请求(即Rollback请求)。
  2、参与者使用阶段1中的Undo信息执行回滚操作,并释放整个事务期间占用的资源。
  3、各参与者向协调者反馈Ack完成的消息。
  4、协调者收到所有参与者反馈的Ack消息后,即完成事务中断。
  
3.2PC的缺陷

  1. 同步阻塞:最大的问题即同步阻塞,即:所有参与事务的逻辑均处于阻塞状态,如果协调者出现故 障,子事务将一直处于锁定状态,无法释放资源,导致资源浪费。
  2. 资源浪费:在假设有1个协调者,9个参与者。其中有一个参与者不具备执行该事务的能力,其余参与者都将资源锁住,执行事务,写入undo和redo日志。协调者收到相应之后,发现有一个参与者不能参与。所以,又出一个roolback消息。其余8个参与者,又对消息进行回滚。这样就会造成资源的浪费。
  3. 脑裂:在阶段2中,如果只有部分参与者接收并执行了Commit请求,会导致节点数据不一致。

3PC

3pc(Three-Phase Commit 三阶段提交协议)
3PC,三阶段提交协议,是2PC的改进版本,即将事务的提交过程分为CanCommit(准备阶段)、PreCommit(预提交阶段)、do Commit(提交阶段)三个阶段来进行处理。
在这里插入图片描述
在这里插入图片描述
1.阶段一:CanCommit
参与者向协调者注册并发送groupId,证明参与者和协调者之间通讯正常,可以执行事务
主要是为了在预执行之前,保证所有参与者都具备可执行条件,从而减少资源浪费。
2.阶段二:PreCommit
此阶段分为两种情况:
1.所有参与者均受到请求并返回YES。
2.有任何一个参与者返回NO,或者有任何一个参与者超时,协调者无法收到反馈,则事务中断
事务预提交:(所有参与者均反馈YES时)
  1、协调者向所有参与者发出PreCommit请求,进入准备阶段。
  2、参与者收到PreCommit请求后,执行事务操作,将Undo和Redo信息记入事务日志中(但不提交事务)。
  3、各参与者向协调者反馈Ack响应或No响应,并等待最终指令。
中断事务:(任何一个参与者反馈NO,或者等待超时后协调者尚无法收到所有参与者的反馈时)
  1、协调者向所有参与者发出abort请求。
  2、无论收到协调者发出的abort请求,或者在等待协调者请求过程中出现超时,参与者均会中断事务。
3.阶段三:do Commit
此阶段也存在两种情况:
  1、所有参与者均反馈Ack响应,即执行真正的事务提交。
  2、任何一个参与者反馈NO,或者等待超时后协调者尚无法收到所有参与者的反馈,即中断事务。
  提交事务:(所有参与者均反馈Ack响应时)
  1、如果协调者处于工作状态,则向所有参与者发出do Commit请求。
  2、参与者收到do Commit请求后,会正式执行事务提交,并释放整个事务期间占用的资源。
  3、各参与者向协调者反馈Ack完成的消息。
  4、协调者收到所有参与者反馈的Ack消息后,即完成事务提交。
  中断事务:(任何一个参与者反馈NO,或者等待超时后协调者尚无法收到所有参与者的反馈时)
  1、如果协调者处于工作状态,向所有参与者发出abort请求。
  2、参与者使用阶段1中的Undo信息执行回滚操作,并释放整个事务期间占用的资源。
  3、各参与者向协调者反馈Ack完成的消息。
  4、协调者收到所有参与者反馈的Ack消息后,即完成事务中断。
  
  注意:进入阶段三后,无论协调者出现问题,或者协调者与参与者网络出现问题,都会导致参与者无法接收到协调者发出的do Commit请求或abort请求。此时,参与者都会在等待超时之后,继续执行事务提交。
  4.3pc提交协议的缺点
如果进入PreCommit后,Coordinator发出的是abort请求,假设只有一个Cohort收到并进行了abort操作,而其他对于系统状态未知的Cohort会根据3PC选择继续Commit,此时系统状态发生不一致性。

2pc和3p的不同

1.对于协调者(Coordinator)和参与者(Cohort)都设置了超时机制(在2PC中,只有协调者拥有超时机制,即如果在一定时间内没有收到参与者cohort的消息则默认失败)。
2.将2PC的准备阶段分为询问阶段和,预提交阶段,使3PC拥有CanCommit、PreCommit、DoCommit三个阶段。CanCommit即询问阶段,也就是子事务与事务管理器先建立通讯,保证所有子事务都可以与事务管理器保持通讯,然后在去PreCommit阶段执行子事务具体的业务,避免2PC不询问直接执行后由于事务管理器无法与其中一个子事务无发通讯导致的回滚操作的资源浪费。

TCC

TCC 其实就是采用的补偿机制,其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。它分为三个阶段:事务发起方在一阶段执行 Try 方式,在二阶段提交执行 Confirm 方法,二阶段回滚执行 Cancel 方法。

TCC 三个方法描述:

Try:资源的检测和预留;
Confirm:执行的业务操作提交;要求 Try 成功 Confirm 一定要能成功;
Cancel:预留资源释放;
Try 方法作为一阶段准备方法,需要做资源的检查和预留。
在扣钱场景下,Try 要做的事情是就是检查账户余额是否充足,预留转账资金,预留的方式就是冻结 A 账户的 转账资金。Try 方法执行之后,账号 A 余额虽然还是 100,但是其中 30 元已经被冻结了,不能被其他事务使用。
二阶段 Confirm 方法执行真正的扣钱操作。Confirm 会使用 Try 阶段冻结的资金,执行账号扣款。Confirm 方法执行之后,账号 A 在一阶段中冻结的 30 元已经被扣除,账号 A 余额变成 70 元 。
如果二阶段是回滚的话,就需要在 Cancel 方法内释放一阶段 Try 冻结的 30 元,使账号 A 的回到初始状态,100 元全部可用。
用户接入 TCC 模式,最重要的事情就是考虑如何将业务模型拆成 2 阶段,实现成 TCC 的 3 个方法,并且保证 Try 成功 Confirm 一定能成功。
在这里插入图片描述

*在扣钱 TCC 资源里,Try 接口预留资源扣除余额,Confirm 接口空操作,Cancel 接口释放资源,增加余额。在加钱 TCC 资源里,Try 接口无需预留资源,空操作;Confirm 接口直接增加余额;Cancel 接口无需释放资源,空操作。

优点: 跟2PC比起来,实现以及流程相对简单了一些,但数据的一致性比2PC也要差一些
缺点: 缺点还是比较明显的,在2,3步中都有可能失败。TCC属于应用层的一种补偿方式,所以需要程序员在实现的时候多写很多补偿的代码,在一些场景中,一些业务流程可能用TCC不太好定义及处理。*

MQ 事务消息

有一些第三方的MQ是支持事务消息的,比如RocketMQ,他们支持事务消息的方式也是类似于采用的二阶段提交,但是市面上一些主流的MQ都是不支持事务消息的,比如 RabbitMQ 和 Kafka 都不支持。

以阿里的 RocketMQ 中间件为例,其思路大致为:

第一阶段Prepared消息,会拿到消息的地址。 第二阶段执行本地事务,第三阶段通过第一阶段拿到的地址去访问消息,并修改状态。

也就是说在业务方法内要想消息队列提交两次请求,一次发送消息和一次确认消息。如果确认消息发送失败了RocketMQ会定期扫描消息集群中的事务消息,这时候发现了Prepared消息,它会向消息发送者确认,所以生产方需要实现一个check接口,RocketMQ会根据发送端设置的策略来决定是回滚还是继续发送确认消息。这样就保证了消息发送与本地事务同时成功或同时失败。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值