历史
这个定理起源于柏克莱加州大学University of California, Berkeley的计算机科学家埃里克·布鲁尔在2000年的分布式计算原则研讨会(Symposium on Principles of Distributed Computing(PODC))上提出的一个猜想。 在2002年,麻省理工学院(MIT)的赛斯·吉尔伯特和南希·林奇发表了布鲁尔猜想的证明,使之成为一个定理。
吉尔伯特和林奇证明的CAP定理比布鲁尔设想的某种程度上更加狭义。定理讨论了在两个互相矛盾的请求到达彼此连接不通的两个不同的分布式节点的时候的处理方案。
CAP介绍
在理论计算机科学中,CAP定理(CAP theorem),又被称作布鲁尔定理(Brewer's theorem),它指出对于一个分布式计算系统来说,不可能同时满足以下三点:
- 一致性(Consistency) (等同于所有节点访问同一份最新的数据副本)
- 可用性(Availability)(每次请求都能获取到非错的响应——但是不保证获取的数据为最新数据)
- 分区容错性(Partition tolerance)(以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择)
根据定理,分布式系统只能满足三项中的两项而不可能满足全部三项。理解CAP理论的最简单方式是想象两个节点分处分区两侧。允许至少一个节点更新状态会导致数据不一致,即丧失了C性质。如果为了保证数据一致性,将分区一侧的节点设置为不可用,那么又丧失了A性质。除非两个节点可以互相通信,才能既保证C又保证A,这又会导致丧失P性质。
CAP证明
我们现在有两个网络N1和N2,每个网络中都存在一个服务用于从db获取数据,初始状态下,db中存储的数据都是V0。
image.png
正常情况下,在网络N1通过服务A更新V0到V1,更新成功后发送消息M使N2 db中的V0变为V1,此时我们通过服务B获取数据时,获取到V1。
此时为CA,没有分区
但是一旦发生了网络分区(分区容错性强制拥有),此时我们通过服务A更新数据到V1后,由于网络错误,V1值同步不到N2网络中去,此时我们调用服务B去请求数据的时候,我们必须从C和A选一个,如果选择C,我们需要等到数据同步到N2,但是从服务B获取数据肯定是失败了,失去了A。如果选择A,那么从B我们获取到的数据不是最新的,失去了C。
分区后,P满足,只能CA之间选择
CAP应用
CAP存在的问题
在CAP理论中,有一点很理想化,它没有考虑网络延迟,他认为C都是立刻生效的,实际上同步这个操作肯定存在延迟。因此对于分布式系统,我们一般都采用AP。
CA取舍
从上面这张图,我们可以看到我们的分布式应用分为三个状态,一致状态,分区状态,分区恢复状态。
对于分布式系统来讲,避免不了分区状态和分区恢复状态,一旦进入,我们必须在C和A之间做出妥协,这个妥协也不是说你只选择C而完全不考虑A,可以在CA的实现比例上进行权衡,比如主A辅C,实现基本可用,最终一致。BASE理论就是用来解决这个问题。
BASE理论
BASE 是 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent (最终一致性)三个短语的缩写,是对 CAP 中 AP 的一个扩展。
基本可用:分布式系统在出现故障时,允许损失部分可用功能,保证核心功能可用。
软状态:允许系统中存在中间状态,这个状态不影响系统可用性,这里指的是 CAP 中的不一致。
最终一致:最终一致是指经过一段时间后,所有节点数据都将会达到一致。
BASE 解决了 CAP 中理论没有网络延迟,在 BASE 中用软状态和最终一致,保证了延迟后的一致性。
BASE 和 ACID 是相反的,它完全不同于 ACID 的强一致性模型,而是通过牺牲强一致性来获得可用性,并允许数据在一段时间内是不一致的,但最终达到一致状态。
BASE理论的意义在于,我们不必在A或C中做出选择,可以实现部分的A和C
应用CAP分析
应用 | 类型 | 其他 |
---|---|---|
Mysql | CA | 主从模式为AP |
ZooKeeper | CP | 在分区后,对于A,只有分区内节点大于quorum才对外服务 |
Eureka | AP | 最终一致性 |
Redis哨兵/集群模式 | AP | 最终一致性,单体肯定是CA |
RocketMQ主从 | AP | 最终一致性 |
分布式事务-2pc | CP | 锁住资源,该资源其他请求阻塞 |
分布式事务-TCC | AP | 最终一致性 |
分布式事务-最大努力尝试 | AP | 最终一致性 |
总结
个人认为,CAP定理的核心在于,在网络分区的情况下,我们需要对C和A做出相应的妥协,我们不可能完全满足CA,但是我们可以合理控制C和A之间的比例让我们的应用/中间件正常提供服务。
下面是我公众号,大家可以关注下。