CAP理论浅析

版权声明:本文为博主原创文章,可以转载但必须注明出处。 https://blog.csdn.net/nirendao/article/details/85058910

CAP理论是分布式的基础理论。关于它的介绍在网上有很多,但其中往往有一些不够清晰或错漏之处,笔者在翻阅了多家文献之后,尝试整理出一份比较简洁清晰的介绍。

1. CAP理论的历史

2000年7月,加州大学伯克利分校的Eric Brewer教授在ACM PODC会议上提出CAP猜想。2年后,麻省理工学院的Seth Gilbert和Nancy Lynch从理论上证明了CAP。之后,CAP理论上升为一个定理。但是,在国外也有很多的质疑者。对于这些质疑,Lynch在2012年重写了论文:缩小CAP使用的定义,消除质疑的场景;展示了CAP在非单一一致性结果下的广阔的研究结果;并顺便暗示了CAP定理依旧正确。关于对CAP理论的质疑以及Lynch的回应,可以参见这篇博客,写得比较精彩。

2. 什么是CAP理论

CAP理论是分布式系统设计中最基础,也是最为关键的理论。它指出,分布式数据存储不可能同时满足以下3个条件:一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)。

这里,需要对一致性、可用性、和分区容错性一一进行解释;然后再对该定理给出一个易于理解的表述。

1> 一致性:

CAP定理中的一致性指的是强一致性。强一致性要求写操作在告知客户端完成时,所有拥有副本的节点都被写入了最新的值。这也就意味着,如果有些副本还在写入的过程中,那么读操作将会失败或阻塞。

2> 可用性:

每次请求都能获得响应,但不保证返回的是最新写入的数据,即返回的是老数据。

在衡量一个系统的可用性的时候,一般用年容忍停机时间来衡量:

可用性 可用水平(%) 年容忍停机时间
容错可用性 99.9999 < 1min
极高可用性 99.999 < 5min
故障自恢复 99.99 < 53min
高可用性 99.9 < 8.8h
商品可用性 99 < 87.6h

3> 分区容错性

这里指的是网络分区容错性。即网络发生了故障,比如,原有的一个大网络,变成了2个互不相通的网络。
看一下笔者上上篇博客中关于Raft协议对网络分片的问题的处理,就是在网络分区的情况下,Raft协议仍支持系统提供服务。Raft和Paxos都是提供强一致性,即满足CP. 

分区容错性可表述为:尽管任意数量的消息被节点间的网络丢失(或延迟),系统仍继续运行。

总结一下CAP定理的实质:
在网络状况良好的时候(即不存在P的时候),CA是可以同时达到的;而在发生网络故障时还要求系统能提供服务(即当P发生时),那么C和A只能取其一。

3. 分析CAP的几种组合情况与应用场景

CAP的组合无非3种:CA、AP、CP

一个著名的图

1> CA without P 

对于这条的理解,有可能发生偏差。比如,有的文章中提到,“这种情况在分布式系统中几乎是不存在的。首先在分布式环境下,网络分区是一个自然的事实。因为分区是必然的,所以如果舍弃P,意味着要舍弃分布式系统。” 但是,在左耳朵耗子的极客时间专栏中是这么说的:“这样的系统关注一致性和可用性,它需要非常严格的全体一致的协议,比如两阶段提交(2PC). CA系统不能容忍网络错误或节点错误,一旦出现这样的问题,整个系统就会拒绝写请求,因为它并不知道对面的那个节点是否挂掉了,还是只是网络问题,唯一安全的就是把自己变成只读的”。 另外,在这篇文章中提到“宣称是CA系统的,目前有两家:一家是Google的Spanner,一家是Alibaba的OceanBase。
由此可见,分布式系统还是有可能做到"CA without P"的,要点就是,一旦发生网络故障,就拒绝写请求。另外,如果不是分布式系统,比如Oracle、MySQL(非MySQL Cluster),也是属于"CA without P"的。


2> CP without A 

这样的系统关注的是大多数人的一致性协议,比如Paxos算法(Quorum类的算法)。这样的系统只保证大多数节点数据一致,而少数的节点会在没有同步到最新版本的数据时变成不可用状态。这样等于是提供了一部分的可用性。

由以上论述可知,CP without A 的几个实例如下:

  • Raft算法(其实是提供了一部分的可用性,并非完全没有可用性);
  • Ceph存储因为采用的Paxos算法,所以它也算是此种情况。
  • ZooKeeper
  • Redis
  • HBase
  • Mongo DB

3> AP without C 

这样的系统比较注重高可用性,也就是说,用户访问时能马上得到反馈;因此也就很容易存在全局数据不一致的情况。这种情况一般指的是失去了强一致性,但是会用最终一致性来弥补。也就是说,过了一段时间,全局数据还是可以达到一致的。

有一个例子是12306,在购票的时候告诉你有票,等到真正进去支付的时候发现其实没有票了。告诉你有票,这就是可用性--得到了系统响应;但是这个响应的值是错误的,因为其数据和真正出票数据库里的数据是不一致的,这就是失去了一致性;但是当没有那么多人访问的时候,购票网页处显示的票数和出票数据库里的剩余票数会最终达到一致的,这就是最终一致性。

实例:

  • DynamoDB
  • Cassandra
  • CoachDB

4. 各种一致性简介

鉴于上面提到了强一致性和最终一致性,下面简介一下各种一致性。

1> 强一致性

    写操作结束后,任何读操作(来自各client访问各节点)都会得到最新的值。  


2> 最终一致性

系统在数据写入成功后,不保证立即可以读到最新写入的值;但是系统保证,在没有后续更新的前提下,经过一定的时间(也不承诺具体多久),可以让数据在分布式系统内达到一致,即任何读操作都能得到最新更新的值。不一致的时间窗口主要受到通信延迟、系统负载、副本个数等因素的影响。


3> 最终一致性的几个变种

a. 因果一致性
    A进程完成写操作后通知B进程,那么B的读操作会拿到最新的值;而没有因果关系的C进程则遵循最终一致性。
   
b. 读己所写一致性
    一个进程总可以读到自己写的数据。
   
c. 会话一致性
    读己所写一致性的实用形式。进程在访问系统的一个会话内,系统保证该进程读己之所写。 
   
d. 单调读一致性
    如果一个进程已经读取过一个值,则该进程不会读到该值以前的任何值。
   
e. 单调写一致性
   系统保证来自同一个进程的写操作顺序执行。

5. 参考文献

[1] 左耳朵耗子极客时间专栏

[2] CAP理论和BASE理论

[3] 分布式系统的CAP理论

[4] CAP理论

[5] 数据一致性和Paxos算法

[6] CAP理论和分布式系统设计

[7] 一致性与可用性:Werner Vogels 谈最终一致性

猜你喜欢

转载自blog.csdn.net/nirendao/article/details/85058910