CAP 定理,只能三选二吗?

大家好,我是猿java

不管你有没有实战过分布式系统,赫赫有名的 CAP 定理一定有所耳闻,今天我们就来聊一聊 CAP 是什么?在分布式系统设计时,CAP 该如何选择?

一、CAP 由来

CAP 定理:CAP Theorem,又被称作布鲁尔定理(Brewer's theorem),它是由加州大学伯克利分校教授埃里克·布鲁尔(Eric Brewer)在 2000 年首次提出,主要是关于搜索引擎、分布式 Web 缓存权衡的一个猜想,直到 2002 年,麻省理工学院的赛斯·吉尔伯特(Seth Gilbert)和 南希·林奇(Nancy Lynch)才提出和发表对该猜想的正式证明,使之成为分布式计算领域公认的一个定理。

埃里克·布鲁尔:

  • 博士
  • 加州大学伯克利分校教授
  • Inktomi 联合创始人兼首席科学家

布埃里克·布鲁尔 CAP 定理猜想

people.eecs.berkeley.edu/~brewer/cs2...

二、CAP 定义

如果你仔细研读过埃里克·布鲁尔 CAP 猜想原文,会发现:在原文,作者并没有详细定义 Consistency、Availability、Partition Tolerance 三个词,因此,作为初学者甚至工作多年的小伙伴,因为学习 CAP 资料的不同,对 CAP 的理解也有所差别。

本文对 CAP 的定义基于 Seth Gilbert 和 Nancy Lynch 的 CAP 证明。

Seth Gilbert 和 Nancy Lynch 的 CAP 证明

groups.csail.mit.edu/tds/papers/...

C:Consistency,一致性

这里的一致性是指强一致性( Strong Consistency )或者线性一致性(Linearizable Consistency ),它要求多节点组成的分布式系统,能够像单节点一样,如果一个写操作返回成功,后面所有的读请求都必须能读到这个新数据,如果写操作返回失败,后面所有的读操作都不能读到这个数据。因此,CAP 中的一致性忽略了网络延时,要求分布式系统节点数据的写入能和单机一样即时。

A:Availability,可用性

可用性要求系统提供的服务必须处于 100% 可用的状态,对于用户的每一个操作请求,系统总能够在有限的时间内返回结果。这里强调的可用性是完全可用,不允许任何不可用的情况出现,因此这是一个非常理想的模型。

目前业内的分布式系统根本达不到 100% 的可用性,常见的可用性有:99.99% (俗称 4 个 9),即一年内服务不可用时长有 50 分钟;99.999%(俗称 5 个 9),即一年内服务不可用时长只有 5 分钟,99.9999%(俗称 6 个 9),即一年内服务不可用时长只有 31秒。

P:Partition tolerance,分区容错性

分区指的是在整个分布式系统中,因为各种网络原因,导致系统被分隔成多个独立的部分,它不仅包含通常意义上的网络分区,也包含因网络丢包导致网络不通的情况。因此,分区容错是指当出现网络分区后,系统能够继续"履行职责"。

如下图:因为网络分区,ATM1 成了一个独立的区域,ATM2 和 ATM3 又成了另外一个区域。

三、CAP 组合

按照 CAP 定理,三个要素中只能取两个,组合如下图:

CA - Consistency/Availability

如下图:账户原余额是 0,在网络状况 ok 时,从 ATM1 存入 <math xmlns="http://www.w3.org/1998/Math/MathML"> 100 ,再从 A T M 2 查询余额也是 100 ,再从 ATM2 查询余额也是 </math>100,再从ATM2查询余额也是100。所以,可以满足 CA。

但是,作为一名程序员,应该很清楚:日常开发中,很多工作都是为了弥补网络异常导致的问题。因此在真实的分布式环境中,网络状况是一个不确定因素,假如忽略网络状况(即忽略 P),只考虑 CA 会出现什么情况?

如下图:账户原余额是 0,当 ATM1 存入 $100 成功后, ATM1 和 ATM2 发生网络分区,为了保证两个 ATM 数据的 C(一致性),ATM 2 需要禁止存款,查询余额等操作,这样 ATM2就不能工作了,和 A(可用性) 冲突;

如下图:当 ATM1 存入 <math xmlns="http://www.w3.org/1998/Math/MathML"> 100 成功后, A T M 1 和 A T M 2 发生网络分区,为了保证两个 A T M 系统的 A (可用性), A T M 2 就必须提供存款,查询余额等操作,但是 A T M 1 存入 100 成功后, ATM1和 ATM2 发生网络分区,为了保证两个 ATM 系统的 A(可用性),ATM2 就必须提供存款,查询余额等操作,但是 ATM1 存入 </math>100成功后,ATM1和ATM2发生网络分区,为了保证两个ATM系统的A(可用性),ATM2就必须提供存款,查询余额等操作,但是ATM1存入100 的信息还未同步给 ATM2,所以,ATM2查询到的账户余额是 0,余额不足,和 C(一致性) 冲突;

因此,分布式系统, 理论上****是不能选择 CA 架构。

CP - Consistency/Partition tolerance

如下图:账户原余额是 0,当从 ATM1 存入 <math xmlns="http://www.w3.org/1998/Math/MathML"> 100 时发生了网络分区, A T M 1 和 A T M 2 无法通信,因此,从 A T M 1 上存入 100 时发生了网络分区,ATM1 和 ATM2 无法通信,因此,从 ATM1 上存入 </math>100时发生了网络分区,ATM1和ATM2无法通信,因此,从ATM1上存入100 的信息无法同步给 ATM2,ATM2 为了保证和 ATM1 数据的一致性,需要拒绝存款或者查询余额等操作,返回 error,这样就牺牲了ATM2 的 A(可用性)。

AP - Availability/Partition tolerance

如下图,账户原余额是 0,当从 ATM1 存入 $100 时发生了网络分区,ATM1 和 ATM2 无法通信,为了保证可用性,ATM 2 必须提供存款,查询余额等操作。注意:尽管 ATM2提供了服务,但是它提供的数据可能是一个错误的,因此牺牲了 C(一致性)。

上文我们用实例分别描述了 CA,CP,AP,因为现实环境中,网络的因素是不可控的,所以在大部分情况下,系统设计都会保留 P 属性,而在 C 和 A 中二选一。但是,在分布式系统的设计中,真的只能三选二吗?

四、CAP 误区

误区一: 三选二有误导性**

这里是一个很容易产生误解的地方,很多资料都强调 CAP 只能选择 CP 或者 AP,但是在计算机的世界,并不是非黑即白。

CAP 定理阐明分布式系统只能选择 CP 或 AP,但这里有一个隐藏的前提:那就是系统发生了"分区"。由于分区很少发生,如果系统不存在分区的情况下没有理由牺牲 C 或 A ,CAP 在大多数时候允许完美的 C 和 A。因此,在架构设计时,既要考虑分区发生时选择 CP 还是 AP,也要考虑没有网络分区时如何保证 CA。

误区二:牺牲不等于什么都不做

CAP 定理阐明三个元素只能取两个,需要"牺牲"(sacrificed)另外一个,这里的"牺牲"只是说在分区时无法同时保证 CA,并不是什么都不做。比如:上文提到的 99.99%、99.999% 或 99.9999% 系统,一年内不可用时长不超过 1小时,因此可以在分区期间牺牲 C 或 A,在分区故障解决后,系统又重新恢复到 CA 状态。

误区三:CAP 忽略了网络延时

CAP 定理的强一致性,要求分布式系统和单点系统一样保证数据写入的即时性,忽略了节点间数据复制有网络延时(也就是说,当有数据写入时,数据能够瞬间复制到所有节点)。实际情况下,数据从节点 A 复制到节点 B,需要花费一定的时间。这就意味着,CAP 理论中的 C 在实践中是不可能完美实现的,在数据复制的过程中,节点 A 和节点 B 的数据并不一致。

通过分析几个误区,我们来回答文章标题:CAP 只能 三选二吗?

CAP 中阐述只能选择 CP 或者 AP,前提是系统出现了分区,存在误导性,因为分区比较少发生,因此在网络状况良好的,CAP都是可以保证的,在架构设计时,既要考虑分区发生时选择 CP 还是 AP,也要考虑没有网络分区时如何保证 CA。

五、ACID 和 BASE

分析完 CAP 之后,就不得不提和 CAP 有千丝万缕关系的 ACID 和 BASE。

ACID 是数据库的传统设计思路,CAP 与 ACID 容易产生误解的一个原因是 ACID 和 CAP有相同的 C、A 字母,但是它们所代表的概念却不同。

A:ACID 中的 A 是 Atomicity,原子性。一个事务中的所有操作,要么全部完成,要么全部失败。CAP 中的 A 是可用性。

C:ACID 中的 C 是 Consistency,一致性。指事务不能破坏任何数据库规则,如键的唯一性。与之相比,CAP 的 C 仅指单一副本这个意义上的一致性,因此只是 ACID 一致性约束的一个严格的子集。

I:Isolation,隔离性。正在处理但尚未提交的事务必须与任何其他事务保持隔离。事务隔离分为:读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。隔离是 CAP 定理的核心:如果系统要求 ACID 隔离性,那么它在分区期间最多可以在分区一侧维持操作。事务的可串行性(serializability)要求全局的通信,因此在分区的情况下不能成立。只要在分区恢复时进行补偿,在分区前后保持一个较弱的正确性定义是可行的。

D:Durability,持久性。事务对数据的修改就是永久的,即便系统故障也不会丢失数据。

BASE,它是 "Basically Available, Soft state, Eventually consistent(基本可用、软状态、最终一致性)"的首字母缩写。其中的软状态和最终一致性这两种技巧擅于对付存在分区的场合,提高了可用性。BASE 中的最终一致性其实是对 CAP 强一致性的一个补充。

六、真实案例

CP 系统

Redis、Google BigTable、Hbase、MongoDB、 MemCacheDB

AP 系统

亚马逊的 DynamoDB、以及衍生物 Apache Cassandra 和 Voldemort

CA 系统

Apache Kafka 是一个比较典型的 CA系统

Kafka 从 0.8 版本之后,引入了 Replication 副本的概念。通过 In-sync-replica(同步数据副本)机制,所有的数据写入都必须在这个领导者节点中记录。另外,通过将数据复制到不同的节点上,从而增强了数据在系统中的持久性(Durability)和可用(Availability)。在 Kafka Replication 的系统设计中,所有的数据日志存储是设计在同一个数据中心(Data Center)里面的,也就是说,在同一个数据中心里网络分区出现的可能性是十分之小的。

七、总结

CAP 是作者埃里克·布鲁尔 的猜想,经过麻省理工学院 赛斯·吉尔伯特(Seth Gilbert)和南希·林奇(Nancy Lynch)的证明。CAP 定理是分布式的一个基础理论,它可以开阔设计师的思路,在多样化的取舍方案下设计出多样化的系统。

CAP 定理强调的是强一致性和 100% 服务可用,但是,在真实分布式环境中 100% 可用只能是一种理想的状态。因此,4个9、5个9、6个9 的系统, 哪怕它不符合 CAP 定理的可用性,也符合工作中对可用性的要求。CAP 的强一致性,在分布式环境的多个节点间,因为数据同步有网络延时,因此也会存在一段时间的不一致。

CAP 定理断言任何基于网络的数据共享系统,最多只能满足数据一致性、可用性、分区容忍性三要素中的两个要素。但是通过显式处理分区情形,系统设计师可以做到优化数据一致性和可用性,进而取得三者之间的平衡。

百种业务百种架构,在架构设计时,既要考虑分区发生时选择 CP 还是 AP,也要考虑没有网络分区时如何保证 CA。

八、参考文献 ******

布埃里克·布鲁尔 CAP 定理猜想

people.eecs.berkeley.edu/~brewer/cs2...
Seth Gilbert 和 Nancy Lynch 的 CAP 证明

groups.csail.mit.edu/tds/papers/...

CAP Twelve Years Later: How the "Rules" Have Changed:

www.infoq.com/articles/ca...

CAP Twelve Years Later: How the "Rules" Have Changed 中文版

www.infoq.cn/article/cap...
CAP Theorem: Explained:

robertgreiner.com/cap-theorem...

相关推荐
Francek Chen2 小时前
【大数据技术基础 | 实验十二】Hive实验:Hive分区
大数据·数据仓库·hive·hadoop·分布式
吾日三省吾码3 小时前
JVM 性能调优
java
LNTON羚通3 小时前
摄像机视频分析软件下载LiteAIServer视频智能分析平台玩手机打电话检测算法技术的实现
算法·目标检测·音视频·监控·视频监控
弗拉唐4 小时前
springBoot,mp,ssm整合案例
java·spring boot·mybatis
oi774 小时前
使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
java·服务器
少说多做3435 小时前
Android 不同情况下使用 runOnUiThread
android·java
知兀5 小时前
Java的方法、基本和引用数据类型
java·笔记·黑马程序员
哭泣的眼泪4085 小时前
解析粗糙度仪在工业制造及材料科学和建筑工程领域的重要性
python·算法·django·virtualenv·pygame
蓝黑20205 小时前
IntelliJ IDEA常用快捷键
java·ide·intellij-idea