CAP 理论
CAP理论被很多人拿来作为分布式系统设计的金律,然而感觉大家对CAP这三个属性的认识却存在不少误区。从CAP的证明中可以看出来,这个理论的成立是需要很明确的对C、A、P三个概念进行界定的前提下的。在本文中笔者希望可以对论文和一些参考资料进行总结并附带一些思考。
一、什么是CAP理论
CAP原本是一个猜想,2000年PODC大会的时候大牛Brewer提出的,他认为在设计一个大规模可扩放的网络服务时候会遇到三个特性:一致性(consistency)、可用性(Availability)、分区容错(partition-tolerance)都需要的情景,然而这是不可能都实现的。之后在2003年的时候,Mit的Gilbert和Lynch就正式的证明了这三个特征确实是不可以兼得的。
二、CAP的概念
Consistency、Availability、Partition-tolerance的提法是由Brewer提出的,而Gilbert和Lynch在证明的过程中改变了Consistency的概念,将其转化为Atomic。Gilbert认为这里所说的Consistency其实就是数据库系统中提到的ACID的另一种表述:一个用户请求要么成功、要么失败,不能处于中间状态(Atomic);一旦一个事务完成,将来的所有事务都必须基于这个完成后的状态(Consistent);未完成的事务不会互相影响(Isolated);一旦一个事务完成,就是持久的(Durable)。
对于Availability,其概念没有变化,指的是对于一个系统而言,所有的请求都应该‘成功’并且收到‘返回’。
对于Partition-tolerance,所指就是分布式系统的容错性。节点crash或者网络分片都不应该导致一个分布式系统停止服务。
三、基本CAP的证明思路
CAP的证明基于异步网络,异步网络也是反映了真实网络中情况的模型。真实的网络系统中,节点之间不可能保持同步,即便是时钟也不可能保持同步,所有的节点依靠获得的消息来进行本地计算和通讯。这个概念其实是相当强的,意味着任何超时判断也是不可能的,因为没有共同的时间标准。之后我们会扩展CAP的证明到弱一点的异步网络中,这个网络中时钟不完全一致,但是时钟运行的步调是一致的,这种系统是允许节点做超时判断的。
CAP的证明很简单,假设两个节点集{G1, G2},由于网络分片导致G1和G2之间所有的通讯都断开了,如果在G1中写,在G2中读刚写的数据, G2中返回的值不可能G1中的写值。由于A的要求,G2一定要返回这次读请求,由于P的存在,导致C一定是不可满足的。
四、CAP的扩展
CAP的证明使用了一些很强的假设,比如纯粹的异步网络,强的C、A、P要求。事实上,我们可以放松某些条件,从而达到妥协。
首先 —— 弱异步网络模型
弱异步网络模型中所有的节点都有一个时钟,并且这些时钟走的步调是一致的,虽然其绝对时间不一定相同,但是彼此的相对时间是固定的,这样系统中的节点可以不仅仅根据收到的消息来决定自己的状态,还可以使用时间来判断状态,比如超时什么的。
在这种场景下,CAP假设依旧是成立的,证明跟上面很相似。
不可能的尝试 —— 放松Availability或者Partition-tolerance
放弃Partition-tolerance意味着把所有的机器搬到一台机器内部,或者放到一个要死大家一起死的机架上(当然机架也可能出现部分失效),这明显违背了我们希望的scalability。
放弃Availability意味着,一旦系统中出现partition这样的错误,系统直接停止服务,这是不能容忍的。
最后的选择 —— 放松一致性
我们可以看出,证明CAP的关键在于对于一致性的强要求。在降低一致性的前提下,可以达到CAP的和谐共处,这也是现在大部分的分布式存储系统所采用的方式:Cassandra、Dynamo等。“Scalability is a bussness concern”是我们降低一致性而不是A和P的关键原因。
Brewer后来提出了BASE (Basically Available, Soft-state, Eventually consistent),作为ACID的替代和补充。
五、战胜CAP
1,2008年9月CTO of atomikos写了一篇文章“A CAP Solution (Proving Brewer Wrong)”,试图达到CAP都得的效果。
这篇文章的核心内容就是放松Gilbert和Lynch证明中的限制:“系统必须同时达到CAP三个属性”,放松到“系统可以不同时达到CAP,而是分时达到”。
Rules Beat CAP:
1) 尽量从数据库中读取数据,如果数据库不能访问,读取缓存中的数据
2) 所有读都必须有版本号
3) 来自客户端的更新操作排队等候执行,update必须包括导致这次更新的读操作的版本信息
4) 分区数量足够低的时候排队等待的update操作开始执行,附带的版本信息用来验证update是否应该执行
5) 不管是确认还是取消更新,所有的结构都异步的发送给请求方
证明:
1) 系统保证了consistency,因为所有的读操作都是基于snapshot的,而不正确的update操作将被拒绝,不会导致错误执行
2) 系统保证了availability,因为所有的读一定会返回,而写也一样,虽然可能会因为排队而返回的比较慢
3) 系统允许节点失效
缺点:
1) 读数据可能会不一致,因为之前的写还在排队
2) partition必须在有限的时间内解决
3) update操作必须在所有的节点上保持同样的顺序
2, 2011年11月Twitter的首席工程师Nathan Marz写了一篇文章,描述了他是如何试图打败CAP定理的: How to beat the CAP theorem
本文中,作者还是非常尊重CAP定律,并表示不是要“击败”CAP,而是尝试对数据存储系统进行重新设计,以可控的复杂度来实现CAP。
Marz认为一个分布式系统面临CAP难题的两大问题就是:在数据库中如何使用不断变化的数据,如何使用算法来更新数据库中的数据。Marz提出了几个由于云计算的兴起而改变的传统概念:
1) 数据不存在update,只存在append操作。这样就把对数据的处理由CRUD变为CR
2) 所有的数据的操作就只剩下Create和Read。把Read作为一个Query来处理,而一个Query就是一个对整个数据集执行一个函数操作。
在这样的模型下,我们使用最终一致性的模型来处理数据,可以保证在P的情况下保证A。而所有的不一致性都可以通过重复进行Query去除掉。Martz认为就是因为要不断的更新数据库中的数据,再加上CAP,才导致那些即便使用最终一致性的系统也会变得无比复杂,需要用到向量时钟、读修复这种技术,而如果系统中不存在会改变的数据,所有的更新都作为创建新数据的方式存在,读数据转化为一次请求,这样就可以避免最终一致性的复杂性,转而拥抱CAP。
具体的做法这里略过。
总结:
其实对于大规模分布式系统来说,CAP是非常稳固的,可以扩展的地方也不多。
它很大程度上限制了大规模计算的能力,通过一些设计方式来绕过CAP管辖的区域或许是下一步大规模系统设计的关键。
--------------- 参考文献 -----------------------
[1] Seth Gilbert and Nancy Lynch. 2002. Brewer's conjecture and the feasibility of consistent, available, partition-tolerant web services. SIGACT News 33, 2 (June 2002), 51-59. DOI=10.1145/564585.564601 http://doi.acm.org/10.1145/564585.564601
[2] Guy Pardon, 2008, A CAP Solution (Proving Brewer Wrong), http://blog.atomikos.com/2008/09/a-cap-solution-proving-brewer-wrong/
[3] Werner Vogels, 2007, Availability & Consistency, http://www.infoq.com/presentations/availability-consistency
[4] Nathan Marz, 2011, How to beat the CAP theorem, http://nathanmarz.com/blog/how-to-beat-the-cap-theorem.html
http://www.cnblogs.com/mmjx/archive/2011/12/19/2290540.html
CAP 理论的更多相关文章
- 《大型网站系统与Java中间件实践》读书笔记——CAP理论
分布式事务希望在多机环境下可以像单机系统那样做到强一致,这需要付出比较大的代价.而在有些场景下,接收状态并不用时刻保持一致,只要最终一致就行. CAP理论是Eric Brewer在2000年7月份的P ...
- 转载:分布式系统的CAP理论
原文转载Hollis原创文章:http://www.hollischuang.com/archives/666 2000年7月,加州大学伯克利分校的Eric Brewer教授在ACM PODC会议上提 ...
- 从分布式一致性谈到CAP理论、BASE理论
问题的提出 在计算机科学领域,分布式一致性是一个相当重要且被广泛探索与论证问题,首先来看三种业务场景. 1.火车站售票 假如说我们的终端用户是一位经常坐火车的旅行家,通常他是去车站的售票处购买车票,然 ...
- CAP理论
自打引入CAP理论的十几年里,设计师和研究者已经以它为理论基础探索了各式各样新颖的分布式系统,甚至到了滥用的程度.NoSQL运动也将CAP理论当作对抗传统关系型数据库的依据. CAP理论主张任何基于网 ...
- 精彩的解释CAP理论的文章
强一致性(Consistency): 更新操作成功并返回客户端完成后,分布式的所有节点在同一时间的数据完全一致. 可用性(Availability):读和写操作都能成功. 分区容错性(Partiti ...
- CAP理论(转)
add by zhj: CAP理论可以简单的理解为一致性,可用性,可分区性,这三者没有办法同时满足.我们使用的关系型数据库,比如MySQL,Postgresql是CA类型, 而Redis,MongoD ...
- 【转】分布式理论-CAP理论
一 CAP理论简述 CAP (Consistency, Availability, Partition Tolerance,) 理论是NoSQL数据库管理系统构建的基础. 强一致性:等同于所 ...
- 分布式领域CAP理论
分布式领域CAP理论,Consistency(一致性), 数据一致更新,所有数据变动都是同步的Availability(可用性), 好的响应性能Partition tolerance(分区容错性) 可 ...
- 分布式系统之CAP理论杂记[转]
分布式系统之CAP理论杂记 http://www.cnblogs.com/highriver/archive/2011/09/15/2176833.html 分布式系统的CAP理论: 理论首先把分布式 ...
- (转)CAP理论十二年回顾:"规则"变了
编者按:由InfoQ主办的全球架构师峰会将于2012年8月10日-12日在深圳举行,为了更好地诠释架构的意义.方法和实践,InfoQ中文站近期会集中发布一批与架构相关的文章,本篇即为其中之一.Info ...
随机推荐
- Liunx Pwd
Linux中用 pwd 命令来查看”当前工作目录“的完整路径. 简单得说,每当你在终端进行操作时,你都会有一个当前工作目录. 在不太确定当前位置时,就会使用pwd来判定当前目录在文件系统内的确切位置. ...
- oracle 使用exp命令 sys用户登录 导出表存为dmp文件
在cmd下面,使用exp命令,格式为 exp \"sys/123456@dbname as sysdba\" file=d:\dmp\test.dmp tables=sys.tes ...
- Numpy array 合并
1.np.vstack() :垂直合并 >>> import numpy as np >>> A = np.array([1,1,1]) >>> ...
- iOS.NS_DEPRECATED_IOS
如何处理被NS_DEPRECATED_IOS标记的selector, 例如:类 AVAudioSession中有: - (BOOL)setPreferredHardwareSampleRate:(do ...
- 201621123008 《Java程序设计》第八周学习总结
1. 本周学习总结 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 源代码: public boolean contains(Object o ...
- Java 使用 jacob 将 word 文档转换为 pdf 文件
网上查询了许许多多的博客,说利用 poi.iText.Jsoup.jdoctopdf.使用 jodconverter 来调用 openOffice 的服务来转换等等,我尝试了很多种,但要么显示不完全, ...
- qt小程序
hello: #include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApp ...
- 关键词提取_textbank
脱离语料库,仅对单篇文档提取 (1) pageRank算法:有向无权,平均分配贡献度 基本思路: 链接数量:一个网页越被其他的网页链接,说明这个网页越重要 链接质量:一个网页被一个越高权值的网页链接, ...
- IOS初级:AFNetworking
狗 日的,第三方框架真j8难搞 1.为什么NS_ASSUME_NONNULL_BEGIN在6.2报错,你他么的还挑IDE,你这是什么态度? 2.还有,你他么的自动给老子转json了,有问过我么? #i ...
- python学习 day2 (3月2日)
.if if else 和 if elif else 的区别是: 前者 判断第一个 判断完第二个 之后还会执行else: 后者是只有满足条件(即都不符合if.elif里的条件时才会进入else) 不清 ...