cap理论

一、概述

 

Eric Brewer 教授提出了非常著名的CAP 理论,后人也论证了CAP 理论的正确性。 CAP理论指出:一个分布式系统不可能同时满足一致性(Consistency),可用性(Availibility) 和分区容忍性(Partition Tolerance)这三个需求。最多只能同时满足其中的两个。

 

二、C、A、P的定义

 

1,一致性(Consistency):

 对于分布式的存储系统,一个数据往往会存在多份。简单的说,一致性会让客户对数据的修改操作(增/删/改)要么在所有的数据副本(在英文文献中常称为 Replica)全部成功,要么全部失败。即,修改操作对于一份数据的所有副本而言,是原子(Atomic)的操作。

如果一个存储系统可以保证一致性,那么则客户读写的数据完全可以保证是最新的。不会发生两个不同的客户端在不同的存储节点中读取到不同副本的 情况。

 

2,可用性(Availability):可用性很简单,顾名思义,就是指在客户端想要访问数据的时候,可以得到响应。但是注意,系统可用(Available)并不代表存储系统所有节点提供的数据是一致的。比如客户端想要读取文章评论,存储系统可以返回客户端数据,但是评论缺少最新的一条。这种情况,我们仍然说系统是可用的。

往往我们会对不同的应用设定一个最长响应时间,超过这个响应时间的服务我们仍然称之为不可用的。

 

3,分区容忍性(Partition Tolerance):如果你的存储系统只运行在一个节点上,要么系统整个崩溃,要么全部运行良好。一旦针对同一服务的存储系统分布到了多个节点后,整个存储系统就存在分区的可能性。比如,两个存储节点之间联通的网络断开(无论长时间或者短暂的),就形成了分区。

对当前的互联网公司(例如Google)来说,为了提高服务质量,同一份数据放置在不同城市乃至不同国家是非常正常的。因此节点之间形成分区也很正常。

Gilbert 和 Lynch 将分区容忍性定义如下:

No set of failures less than total network failureis allowed to cause the system to respond incorrectly除全部网络节点全部故障以外,所有子节点集合的故障都不允许导致整个系统不正确响应。

 

三、不能满足的CAP博弈:CAP 说明:在设计一个分布式存储系统时,你不得不在三个特性中选择放弃一个。

 

1,选择C、P

 

如果选择Partition Tolerance 和Consistency,那么即使坏了节点,操作必须 又一致,又能顺利完成。所以就必须 100%保证所有节点之间有很好的连通性。这是很难做到的。最好的办法就是将所有数据放到同一个节点中。但是 显然这种设计是不满足 Availability 的。

 

2,选择C、A

 

如果要满足Availability 和Consistency,那么,为了保证可用,数据必须要有 Replica。这样,系统显然无法容忍 Partition。当同一数据的两个副本 (Replica) 分配到了两个无法通信的 Partition 上时, 显然会返回错误的数据。

 

3,选择A、P

 

最后看一下满足Availability 和Partition Tolerance的情况。满足可用,就说 明数据必须要在不同节点中有 replica。 然而还必须保证在产生 Partition 的时 候仍然操作可以完成。那么,必然操作无法保证一致性。

Yammer的Coda Hale和Cloudera的HenryRobinson都阐述过,分区容错性是不能牺牲的。因此只能在一致性和可用性上做取舍,如何处理这种取舍正是目前NoSQL数据库的核心焦点。
 

1)、选择一致性而不是可用性的系统将面临一些尴尬的问题,当系统不可用时怎么办?你可以对写操作进行缓冲处理,但如果存储缓冲数据的机器出现故障,客户端将丢失写入的值。同样地,缓冲写也可以被认为是一种非一致性的操作,因为客户端认为成功的写入实际上并没有写入到实际的数据库中。当然,系统可以在机器不可用时向客户端返回错误,但可以想象,一个经常告诉客户端“请重试”的产品是多么令人讨厌。


2)、 另一个方案是选择可用性放弃一致性。这种情况下最好的一致性保障是“最终一致性”(EventuallyConsistency)。当使用最终一致性的系统时,客户端有时会读到与刚刚写入数据不同的数据。有时候,同一时间同一个key的多个请求有可能返回不同的结果。数据更新并不能及时在所有的复制节点上生效,所以不同的复制节点上可能读取到的是不同的值。当你检测到数据不一致性时,你需要进行修复(Repair)操作,这就需要使用矢量时钟(vectorclock)记录数据的版本历史并合并不同的数据更新(这称为读取修复,readrepair)。我相信在应用层维护最终一致性对开发人员负担太重,开发人员极易弄错读取修复的代码,而一旦开发人员犯错,有问题的读取修复将对数据库系统造成不可逆的损坏。

3)、所以牺牲可用性时问题会很多,牺牲一致性时构建和维护系统的复杂度又很高,但这里又只有两个选择,不管怎样做都会不完美。CAP定理是改不了的,那么还有什么其他可能的选择吗? 

实际上,还有一个办法:你并不能避开CAP定理,但可以把复杂的问题独立出来,免得你丧失对整个系统的掌控能力。CAP定理带来的复杂性,其实是我们如何构建数据系统这一根本问题的体现。其中有两点特别重要:数据库中可变状态和更新状态的增量算法。复杂性正是这两点和CAP定理之间的相互作用导致的。

有一种方案是从数据库的设计层面来寻找突破口:

数据库系统是一个要回答数据集问题的系统,这些问题我们称之为“查询”。上面的方程表明,查询就是数据上的一个函数。

在关系型数据库当中,对数据增删改查等操作,以满足数据的读写需求。我们知道数据有两个属性:
1)数据是和时间相关的,都是在描述一个真实场景,是真实存在的,所以不用删除
2)数据无法改变。因为数据是和时间相关的,那一个时间发生的场景是无法改变的,所以不用更新

这样实质上对数据库来说是需要进行2种操作:读取数据和增加数据



 

四、现实中的例子

 

基于ACID 的关系型数据库选择的是C 和 P。因此能够提供很高的一致性, 但是却在系统繁忙的时候不可用(Service Unavailable)。但是对于大多数互联网应用来讲,强一致性对他们来说并不一定非要满足,可用性往往是更加重要的。比如,某博客网站在北京和上海的存储服务器突然不联通,北京用户和上海用户无法看到对方的评论显然要比北京用户和上海用户访问网站都返回 HTTP 500错误要好的多。

当然,对于银行这种业务来讲,一致性是不能放弃的。这不在我们的讨论范围之内。

 

五、可被独立的“CAP”

 

由上可知,我们无法避免CAP理论带来的复杂问题,但我们可以将其独立出来加以简化,支持集中化事务处理的实时层和支持并发访问的批处理层的结合,就是一种崭新的解决思路。(详见我的另一篇转载文章:我的淘宝之路18:CAP理论[转])

发布了49 篇原创文章 · 获赞 0 · 访问量 40万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览