架构解密:从分布式到微服务(第2版)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.4 经典的CAP理论

CAP理论在互联网界有着广泛的知名度,被称为“帽子理论”,它是由Eric Brewer教授在2000年举行的ACM研讨会上提出的一个著名猜想:一致性(Consistency)、可用性(Availability)、分区容错(Partition-tolerance)无法在分布式系统中被同时满足,并且最多只能满足其中两个!2003年,MIT的Gilbert和Lynch正式证明了这三者确实是不可兼得的。而后CAP被奉为分布式领域的重要理论,被很多人当作分布式系统设计的金律。

Brewer教授当时想象的分布式场景是在一组Web Service后台运行着众多Server,对Service的读写反映给后台的Server集群,并对CAP给出了如下定义。

● 一致性(C):所有节点上的数据都时刻保持同步。

● 可用性(A):每个请求都能接收一个响应,无论响应成功或失败。

● 分区容错(P):系统应该能持续提供服务,即使系统内部(某个节点分区)有消息丢失。

一致性与可用性属于分布式系统的固有属性。分区容错是网络相关的一个属性,常见的几种分区如下。

● 交换机失败,导致网络被分成几个子网,形成脑裂。

● 服务器发生网络延时或死机,导致某些Server与集群中的其他机器失去联系。

现在我们明白了,分区是分布式系统固有的可靠性问题所导致的一个紊乱的集群状态。从这三个概念的本质来看,CAP理论的准确描述不应该是从3个特性中选择两个(2/3),因为分区本身就是分布式集群固有的特性,我们只能被迫适应,根本没有选择权!有人就此质疑并且提出CAP理论应该如下所示描述。

在一个允许网络发生故障(P)的系统中,我们设计分布式系统时应该选择哪一个目标:保持数据一致性(C)还是系统可用性(A)?

当集群中的机器数量持续增加时,一致性会加剧系统的响应延时,同时导致资源消耗加剧,使维护一致性的成本非常高,在这种情况下,我们基本上只剩下一种选择:在允许网络失败的系统中,更多地选择可用性而放弃一致性。而ZooKeeper、Hadoop之所以选择一致性,是因为这些系统多数是由少量节点所构成的分布式集群!

在CAP理论出来以后,各种质疑不断,有人提出:应该放弃分区容错,因为在局域网中分区很少发生;而在广域网中有各种备选方案,导致实际的分区也较少发生,并且很多人一致认为分区同时蕴涵着不可用,这两个概念之间存在重叠。还有一些重要的质疑包括CAP无法用于分布式数据库事务,比如应用因为更新一些错误的数据而导致失败,此时无论使用什么样的高可用方案都是徒劳的,因为数据发生了无法修正的错误!也有质疑者结合了数据分区导致不可用的一些案例,说明CAP理论并不能用于分布式数据库事务领域。

面对铺天盖地的质疑,在CAP理论诞生12年后,CAP之父Brewer和Lynch纷纷出来澄清。首先是Brewer给出重要修订:“3个中的两个”这个表述是不准确的,这个说法过于简化了复杂场景和问题领域;在某些分区极少发生的情况下,三者能顺畅地配合。

Lynch也在2012年重写了之前的论文,该论文的重点如下。

● 把CAP理论的证明局限在原子读写的场景中,并声明不支持数据库事务之类的场景。

● 把分区容错归结为一个对网络环境的陈述,而非之前的一个独立条件。这实际上更加明确了概念。

● 引入了活性(Liveness)和安全属性(Safety),在一个更抽象的概念下研究分布式系统,并认为CAP是在活性与安全属性之间权衡的一个特例。其中一致性属于活性,可用性属于安全性。

● 把CAP的研究推到一个更广阔的空间:网络存在同步、部分同步;一致性的结果也从仅存在一个到存在N个(部分一致);引入了通信周期Round,并引用了其他论文,给出了为了保证N个一致性结果,至少需要通信的Round数量。还介绍了其他人的一些成果,这些成果分别对CAP的某一方面做出了特殊贡献。

我们不难发现,Lynch在论文中主要做了如下事情。

● 承认分区容错是一个既定的环境约束,而非独立的选择或者条件。

● 缩小CAP适用的定义,消除质疑的场景。

● 建立更精确的理论模型。

● 暗示CAP理论依旧正确。

这里总结一下CAP理论:可以肯定的是,CAP并非一个放之四海而皆准的普适性原理和指导思想,它仅适用于原子读写的NoSQL场景中,并不适用于数据库系统;当今的分布式系统早已不是十年前的简单系统了,现在分布式系统有很多特性如扩展性、自动化等,架构师在进行系统设计和开发时,视野要更加开拓,而不仅仅局限在CAP问题上。