分布式事务-CAP、BASE、2PC和3PC

657 阅读11分钟

前言

在讨论分布式系统的时候,我们必然要熟悉分布式事务这一块的内容。本篇我们先聊聊分布式相关的基础理论。本文会从本地事务切入到CAP、BASE理论,最后着重介绍2PC与3PC之间的原理与异同.

本地事务

在谈论分布式事务之前,我们先看看什么是本地事务。
本地事务就是我们常说的数据库事务,或者说是传统的事务。在实现上,通过Spring的@Transaction注解即可实现。它能够保证ACID特性。那么我们就需要思考,既然本地事务的实现已经非常成熟,那为什么还会出现分布式事务? 是因为随着海量数据处理、以及分布式技术的出现,使得传统的单机数据库或者单机服务,已经不能满足我们的需求。这个时候,业内有人提出了CAP理论,并给予了相关的论证。

CAP理论

什么是CAP?

指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。 (来源:百度百科)

这里我想谈一下什么是分区容错性?
举个具体的例子:某商城的商品库或者服务,部署在了上海的某个移动机房。正常情况下是可以和外界保持通信并提供服务的,但是某一天由于道路施工,路人甲不小心挖断了该机房的出口光纤,那么结果就会导致在修复完成前,用户都无法浏览整个的商品信息。因此为了避免这种情况,就需要将商品库或者服务分别部署在上海和南京,这样的话,即使其中一个出现了问题,那另一地点的机房仍然可以对外提供服务。这就是所谓的分区容错,即通过网络分区,进行一定的容错。那也有可能两个机房全都挂掉的情况,这时候,可以进行多地的备份,这样就可以提高系统的可用性。但是备份的机房越多,可用性是提高了,但是又会引入另外一个问题,就是数据一致性的问题。

例如库存只有一个的情况下,张三下单完成之后,上海机房的商品数量立即扣1,随后南京和北京的库存同样清零。但由于北京机房的网络刚好出现较大的延迟,而此刻用户李四又过来下单,那这时候就会出现超卖的情况,原因就是由于提高了系统和服务的可用性,而降低了数据的一致。

因此我们在设计架构的时候,往往在一致性C和可用性A上进行取舍。例如Zookeeper就是保留了强一致性特性,而Eureka则是保留了可用性特性。

BASE理论

由于CAP理论在可用性和一致性方面无法同时满足,这时候又有人提出了BASE理论。我们来看一下它的定义

BASE 理论是对 CAP 中的一致性和可用性进行一个权衡的结果,理论的核心思想就是:我们无法做到强一致,但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性。(来源:百度百科)

根据定义,可以得知,BASE理论,其实就在保证CAP理论的可用性基础上,确保最终一致性的一种进化理论。关于最终一致性的几种类型,见下图。

2PC两阶段提交事务

在了解了分布式的一些理论概念之后,我们在谈谈什么是分布式事务。所谓分布式事务,是相较于传统的本地事务而言的。
在微服务时代,一次请求往往会涉及到多个服务的调用链,且这些服务部署在了众多的机器之中,想要依靠传统的数据库事务来保证,完全是无法做到的。这个时候,2PC的作用就显现出来了。

我们先来熟悉几个名词:
2PC:Two Phase Commitment Protocol, 如下图所示,分为预提交和最终提交两个阶段。故此得名。
TM:事务管理器,或者称为协调者。负责事务流程操作的调度。
RM:资源管理器,或者称为参与者。负责事务的执行。

有了上面的概念之后,我们再看2PC的过程。下面看一下2PC的执行流程图:

  • 一阶段: 此时协调者TM会向参与此次事务的所有的参与者RM发出第一次请求,要求所有的RM尝试执行一次不做提交的SQL操作(仅仅将UNDO和REDO日志文件写入事务日志中),并给出反馈。这个时候,只有当所有的参与者都返回OK之后,TM才会向所有的RM发出第二次请求发出commit请求;有一个RM返回失败或者超时,则会发送rollback请求进行回滚。

  • 二阶段 和一阶段不同的是,该阶段会进行SQL的提交或回滚操作。TM会根据一阶段各个RM给出的反馈,得到"提交"或"回滚"指令:
         如果TM给出的指令是提交,则该阶段会执行commit操作,完成事务;
         如果TM给出的是回滚,则该阶段会进行回滚,完成事务中断。

至此,两阶段事务提交就完成了,是不是很简答?但这里,我们还需要思考2阶段存在的优缺点。

优点:
原理简单,实现方便

缺点:
同步阻塞
在二阶段提交的所有过程中,所有的节点都在等待其他节点的响应,无法进行其他操作。
这种同步阻塞极大的限制了分布式系统的性能。

单点问题
协调者在整个二阶段提交过程中很重要,如果协调者TM在提交阶段出现问题,例如服务宕掉,那么整个流程将无法运转。
更重要的是,其他参与者将会处于一直"锁定事务资源"的状态中,而无法继续完成事务操作。
2PC事务管理,只有RM参与者有超时机制,而TM协调者没有。所以当TM收不到RM的反馈时,还可以根据超时机制进行判断处理。
但当TM自身挂掉之后,就没法判断了。

数据不一致
假设当协调者TM向所有的参与者发送commit请求之后,发生了局部网络异常,
或者是协调者在尚未发送完所有 commit请求之前自身发生了崩溃,导致最终只有部分参与者RM收到了commit请求。
这就会导致严重的数据不一致问题。

容错性不好
如果在二阶段提交的提交询问阶段中,参与者RM出现故障,导致协调者始终无法获取到所有参与者的确认信息,
这时协调者只能依靠其自身的超时机制,判断是否需要中断事务。
显然,这种策略过于保守。 换句话说,二阶段提交协议没有设计较为完善的容错机制,任意一个节点是失败都会导致整个事务的失败。

2PC单点问题的三种情况

  • TM协调者正常,RM参与者宕机

此时TM由于收不到部分或者全部的RM的反馈,会造成整个节点的阻塞。因此2PC引入了超时处理机制,当TM未能及时收到来自RM的反馈时,TM便会发起回滚操作,来终止本次事务。

  • RM参与者正常,TM协调者宕机

协调者宕机,那会造成整个事务节点的阻塞。因此,我们可以通过备份TM节点的方式,对操作日志进行备份和同步,当检测到TM宕掉之后,启用TM备份机,并根据备份的日志,重新恢复事务操作。

  • TM协调者和RM参与者都宕机 这里又要分为三种情况来分析
  • 发生在第一阶段:在第一阶段,由于参与者RM,并未提交,重新投票选出一个新的协调者,再重新执行第一阶段和第二阶段就可以了。
  • 发生在第二阶段, 并且TM在挂掉之前,还没来得及发送commit或者rollback给其他RM的时候,挂掉了:那么这个时候,事务也并未提交,只要两边恢复之后,重新执行第一阶段和第二阶段就可以了。实际上和第一种情况比较类似。
  • 发生在第二阶段,并且TM发送了一部分的commit或者rollback给了其他RM,也就是说一部分参与者已经执行完commit操作,而一部分未收到指令就挂掉了,此时就出现了数据不一致的地方。此问题2PC无解,这就需要下面所说的补偿方案了。

关于2PC的补偿方案

前面已经讨论了2PC存在数据不一致的情况,那怎么去处理这些问题?常用的方案有三种:人工补偿方式定时任务方式脚本补偿等三种方式。

总结

基于2PC的分布式事务的解决方案,原理和实现都比较简单,能够解决大部分的分布式事务问题。但由于其在整个过程中会锁定资源,造成同步阻塞,因此其不适合于高并发的场景;并且还可能出现需要人工或者脚本干预数据不一致的情况,当然目前的技术,对2PC这一类的柔性分布式事务,也确实还没法做到像本地事务那样的保证数据的一致性,只能是不断的降低出错发生的概率。

3PC三阶段提交事务

3PC是2PC的改进版,同样包括了参与者和协调者。下面我们分阶段来分析3PC的过程。

  • 一阶段

该阶段的示意图如上图所示。协调者TM发出获取问询的指令给所有的参与者RM,RM接收到指令后,会去尝试获取数据库的锁。完成后,若能够获取到锁,则返回Yes,并准备进入第二阶段的预备阶段;获取不到锁,则给出No的反馈。
该阶段不会对资源进行锁定操作,所以相较于2PC,性能上有了较大的提高。

  • 二阶段

若在第一阶段返回的是Yes,则会进入该阶段。从该阶段开始,会对资源进行锁定。该阶段和2PC的第一阶段相似,都会执行sql,但不会提交。会将UNDO和REDO文件写入到事务日志中。每个参与者RM,在完成该阶段后,给出反馈 成功"ACK" 或者 失败"No" 到协调者TM。

  • 三阶段 三阶段分为两种情况:提交和回滚。
  1. 提交

存在两种情况,RM会在三阶段提交事务,如下:

  • 当TM向所有的RM发出ACK时候,RM在收到ACK指令后,进行事务的提交。完成后给出响应,并释放锁定的资源
  • TM宕机或者网络超时,导致RM未能即时收到TM发出的指令:此时RM就会触发"超时默认提交"。这里相较于2PC的一个优化,在2PC中,若TM挂掉了,就会造成资源的阻塞。而在3PC中,RM会默认进行提交,3PC的设计者认为,在前两个阶段都是OK的,那么第三个阶段大概率也是OK的,于是就给出了这一超时自动提交的机制。
  1. 回滚:

当TM发出rollback指令后,RM会回滚之前的操作,中断事务,并释放数据库锁等资源。

  • 3PC总结

3PC在2PC的基础上,做了两点改进:

  • 增加了canCommit阶段,由于该阶段不锁定资源,所以降低了阻塞时,资源被锁定的概率。
  • 在TM和RM中都引入了超时机制:2PC只在TM中设置了超时机制(TM不能及时接收到RM的反馈时,会触发回滚);而3PC在RM中也设置了超时自动提交的处理机制。

我们最后用一张流程图来说明3PC的过程

总结

本篇介绍了CAP、BASE、2PC、3PC理论基础,这些理论,是很多分布式事务框架的理论基础,理解它们,有助于我们对框架的认识和理解。