浅谈CAP理论
有一千个程序员,就有一千种对CAP的解读
喜欢足球的同学都知道帽子戏法,意指同一名球员在一场比赛中连进三球如同魔术师从空空如也的帽子中连续变出鸽子般令人难以置信的戏法。而分布式系统的CAP理论除了名字上沾带帽子的单词外,其他均与之只有毛线的关系。
然而就是这简单三字的背后,竟也是百家争鸣,各有解读。
有简单将P理解为“分布”的,认为分布式系统天然就P了,于是在CAP三者只可得其二的诅咒下,放弃C成了顺理成章。
也有将CAP定理奉为圭臬的,设计系统前先一棍子将AC打散伙,在非强一致性的不归路上越走越远。
不能吃。CAP理论即指C、A、P,三者不可全得,只能选二。以下先分别谈谈:
C(Consistency)为一致性,直译为一物与另一物完全一样。虽然世界上没有两片相同的树叶,但是互联网的世界却大为不同,观察它的人们对精度要求本来不高,而置身其中的事物本身又有很精确的内在形式,以至于我们几乎可以复制出一模一样的东西来;反之,要让它不“一致”也是轻而易举。
因此,一致性也分不同级别,比如强一致性、会话一致性、弱一致性等等。在论证本定理时,C一般指强一致性。将系统作为一个整体,强一致性表现为一旦将外部的“数据”写入系统成功(此时数据必然在系统内部各种转换、分片、复制……),在此后的任意时间点、通过系统提供的任意对外服务节点都能读到最新写入的“数据”(数据不一定要在对外节点本身存储),也即读取的数据与写入的数据一致。
A(Availability)为可用性,指系统能提供正常服务的程度。一个系统的可用性永远不可能达到100%,因为——凡人皆有一死而万物也不例外,谁也不知道什么时候某个节点就挂了。一般可以用 服务可用时间/总服务时间 去度量。
比如4个9的可用性,即99.99%,换算到一年的时间内,可以反推出最长故障时间: 365 × 86400 ×(1-99.99%)秒=3153.6秒=52.56分钟。 也就是要达到4个9的可用性,一年停服时间不能大于52.56分钟。而故障发生时,如果依靠人工去处理,从睡梦中醒来接到NOC告警、VPN爬到机器看log、输入token看曲线、翻开源码定位原因到最终解决问题,只怕一次就把4个9搞没了。
所以保证系统各个环节无单点、大部分故障可自愈是保障高可用性的关键。
P(Partition Tolerance)为分区容错性,或者分区容忍性。P是三种当中最不易理解,也是得到各种解读的根源。它本身最不好量化。
分区容错,先解释下分区(Partition)。对于一个分布式系统,物理上多机分布是其基本形态,多机(多节点点)之间的通信,众所周知为异步不可靠的网络,可能丢包、乱序、重传甚至被篡改,你能想到的意外这里都有。而分区,其实就是网络故障的一种特殊情况:分区两边的节点之间完全不可通信(其实就是在某一段时间内,互相收不到任何应答)。比如分布在两个IDC的节点,两IDC只通过一条光纤连接,而光纤恰好被修路工人一锄头挖断了,在光纤被被挖断到接上之前的这段时间内就形成了一个分区,两个IDC间无法通信,而IDC内则往来如常。 节点分布越多,分区情况越复杂,同时形成多个分区都有可能。
而分区容错(P)的意思,就是在分区发生的情况下,当外部请求到来时,你怎么处理这种错误,在提供什么程度服务和保证怎样的一致性下的一种权衡取舍策略。
策略1:以当前可以触达的节点为用户提供力所能及的服务,保证可用性。如果此时有对数据进行读写操作,是没法和分区另一侧沟通的,既可能读不到另一侧最新的数据也可能这一侧新修改的数据同步不到对侧去,此时C被牺牲了————舍C取A。
策略2:担心提供给用户的不是最新的数据(最新的数据可能恰好在分区另一侧)而拒绝服务保证强一致性C————舍A取C。
这也正是CAP三者只可取其二的原因。细心的同学已经发现了,三取二的组合,可不止CP和AP,还有CA呢? 那我要CA好了,一致服务好,完美!
前面都说了分布式的服务,必然会遇上分区,一旦遇上分区,P就由不得你不选了。然而,在单节点(单机)服务的时代CA是可能的,正是mysql所一直坚持的,在单机的领域将CA做到了极致。然而,三选二,我们就么就范了么? 这事还没完。
如何打败交给它了[2]。 理论之所以是理论,在理论上打败它是不可能的,我们得换一个维度。
工程实践和理论的区别,实在有如天壤。理论上构建的模型,往往忽略了很多细节,而对这些细节的探究、打磨正是互联网一代对极致体验孜孜追求的体现。
对一个分布式系统,如果没有分区,一切都好好的,该读读,该写写,读写的方式有无数种,Master-Secondary,Paxos(无master),Master-Master…… 而多节点分布,遇上分区是个概率问题,迟早的事。一旦遇上分区,我们就被CAP逼上了绝路,对C、A进行取舍,正是P的体现。你若想掩耳盗铃,说我才不管呢,那你其实已经做出了选择,你不管分区、不去识别它,它就是一个普通的网络故障,意味着你牺牲了A。
然而,刚说了,分区是个概率问题,并且发生概率并不大,特别是在同一个IDC内。于是,我们扣住这个细节,我们的系统大部分情况下面对的其实没有分区,也就不需要P,这时有什么理由不选择CA呢?
同时,有策略1、策略2,难道就没有策略3?如果C是只强一致性,还真没有策略3,然而如果我们能在此时稍微降低一致性的要求(各自分区内仍然保证强一致性),并在分区结束后提供补偿措施,修正全局的一致性,是否又有一番新天地? (更多请看参考[1],对这一理论叙述过程的汉文字表达中,在我看过的文章里,只有这一篇最为清晰)
单机部署的mysql,其实就是CA的,因为没有分区,也就不需要考虑P
paxos/raft所实现的分布式服务中,以zk为代表,首先它是强一致性的,这是它的核心诉求;其次当出现分区的时候,并非是完全不可用的,它提供了在大多数节点连通的情况下的可用性保证。
比如发生了分区,某一个分区内部仍然有过半数节点,而外部用户可以访问到这些节点之一,则服务基本不受影响。有不错的A。
两阶段提交协议中任意一节点与协调节点之间发生了分区,则服务完全终止。
quorum机制,即R+W>N,比如N=5,R=2,W=4。R=2,在任意2个节点连通的情况下,一定程度可以读到最新的数据(但也可能并不是W=4写成功的数据),一致性会稍微差一些,弥补了A的不足。 可通过调整R、W的值,在A、C间取得平衡。
quorum_kv虽然也是用的quorum,但是较为特殊,其中N=3(数据只有2份,版本有3份),在R=W=2的情况下是可以保证强一致性的。
并且kv是按uin分片的,不同分片间之间关联甚弱(同一个分片作为一个整体类似一个set,但是不同分片的数据其实又是交叉分布的,复用了机器)。 当某一分片出现了分区时,影响也只是在那一分内部。kv作为一个整体,分布在两地三中心,对外的表现,就能容忍一定程度的分区,在选择强一致性的诉求上,保障了一定程度的A。
以上针对的都是一些通用的服务,能做的事情比较少。而CAP真正能引发人思考的是作为一个产品本身,如果要做到完美,其背后势必要慎重考虑。
比如Google Doc,断网的情况下(其实就是分区发生了)还是可以进行部分操作的,它选择A的时候放弃了C吗?其实并没有,在网络连通的时候,它会做一个合并。这是最艰难的时刻,一致性能否恢复,是需要在分区情况下提前考虑并做好准备的。gdoc的做法就是限制一些容易引发冲突的操作,比如编辑某一个已有内容的单元格是不允许的。(嘿,我刚刚试了,修改字体、颜色什么的也不可以:)
其他比如git,在分区后(其实是用户主动分区- -),有一个专门的合并算法处理一致性问题,遇到无法处理的冲突(小部分情况下),把选择权交给了用户,而用户早已习惯了这种冲突解决,于是皆大欢喜。
我们的产品里面,qzone也是做的不错的,说说最近出的一个功能叫“离线也能发说说”,可用性做到了极致。当然它的分区后合并策略是很简单的,因为说说的功能本身只能新增。
现实中呢?其实也会遇到这种情况(以下通篇瞎扯),比如部门定了一个愿景为“连接游戏与用户”,需要继续分解到小组、个人,才能执行下去。于是各老大准备先在小组内部开一个讨论会(分区发生了),a小组讨论的结果为“丰富活动形式、增加更多福利”(分区内强一致性),这是从用户角度考虑的,几乎可以执行了;b小组讨论的结果为“平台能力建设”,也不差;c小组讨论的结果为“社交化探索”,初见眉目。
然后就到了部门总体会议(分区结束),哈哈,世界很美好啊,完全没有冲突,于是各自开始执行,整体达成了一致。为什么会有这么美好的事情呢?其实这是组织架构划分得当的结果,运营、开发、产品本来就属于不同的sharding了,这是个伪P问题。
真正出现P的时候是各节点群事先都没有分工,需要讨论出一个一致的目标,于是就会出现a部门的愿景为“快乐工作”,b部门的愿景为“力争行业第一”,a、b各自在小范围内,大家积极讨论(A)并达成了一致(分区内C),这时就是boss们头疼了(分区结束了,需要解决一致性的问题)。 然而只要在系统没有对外部造成实质影响前,CAP是可以大作文章的。比如先承诺我们在2个星期内解决(异步),既给了上面一个交代,又没有立刻给出一个将来可能需要否决的结果。当然,2个星期后问题肯定解决了,欲知后事如何,请听下回分解。
[3] 这本书整理得分布式原理相当条理清晰,Lease/Quruom/2PC/Paxos/CAP等介绍非常赞,推荐一读。(不过,其中对Paxos的示例描述中缺少一个变量,会妨碍其正确性,这里显然已经写不下了,下回再说:)
[1] CAP理论十二年回顾:”规则”变了 http://www.infoq.com/cn/articles/cap-twelve-years-later-how-the-rules-have-changed/
[2] Twitter首席工程师:如何“打败”CAP定理 http://kb.cnblogs.com/page/124567/
http://stackoverflow.com/questions/26255211/how-availability-works-in-cap-theorem-ap-inside-out
http://blog.nahurst.com/visual-guide-to-nosql-systems
[3] 刘杰, 分布式系统原理介绍 http://wenku.baidu.com/link?url=oLjEmnQfOjSgkm8iXWIL9tmjZ5IgvK6AMMO_KF2JK1EI848th6dw0LAxLqS0iKAfLnc6MvQGXwzjeXThH5rE-eevaJmZHjuV640VLdRrtau
[4] 如何正确理解CAP理论? http://www.jdon.com/bigdata/how-to-understand-cap.html
[5] 深入懂得CAP理论 http://www.reader8.cn/jiaocheng/20120722/2205612.html
[6] 谈正确理解 CAP 理论 http://foxmile.blog.163.com/blog/static/81169805201201803657204/