CAP原则学习笔记

最近在学习消息中间件的时候,接触到了分布式系统,进而接触到CAP理论,上一次接触还是在年初的时候公司的技术分享会上,有人在介绍项目的时候简单介绍了这个CAP理论,但并没有深入研究。这次,该是时候研究一下这个CAP原则到底是个啥了。
其实,CAP理论在大部分的开发者心里都有一定的位置,在互联网界也有广泛的知名度,稍微经验丰富或者知识广泛的程序员都会把它作为衡量一个系统,尤其是分布式系统的设计准则,也就是我们说的CAP原则。大家都非常清晰的知道:任何的分布式系统,在可用性、一致性和分区容错性方面,是不可兼得的,就像是我们常说的“鱼和熊掌不可兼得”一样,最多值能得其二。所以说,任何一个分布式系统的设计,都是根据各自的实际应用场景和需求,对这三个维度的的不同取舍而已。
 
说了这么多,大家可能还是比较懵逼。到底什么是CAP原则?下面先知道下它的定义:


CAP原则又称CAP定理,指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。换句话说,就是说在一个系统中对某个数据不存在一个算法同时满足 Consistency, Availability, Partition-tolerance。


 
定义就是定义,一句话,就把上面的一大段废话说的清晰明了!那可能接下来,又来了个“三脸懵逼”,到底啥是一致性、可用性和分区容错性?同样的,上定义:


● 一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。一致性被称为原子对象,任何的读写都应该看起来是“原子“的,或串行的。(等同于所有节点访问同一份最新的数据副本)
● 可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
● 分区容错性(P):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。


 
现在大家应该对这些基本概念有了一个比较清晰的认识。那我们在深入理解CAP原则之前,先了解下CAP原则的前世今生。
 
为什么会产生这个CAP理论?
 
1985年Lynch证明了异步通信中不存在任何一致性的分布式算法(FLP Impossibility)的同时,人们就开始寻找分布式系统设计的各种因素。一致性算法既然不存在,但若能找到一些设计因素,并进行适当的取舍以最大限度满足实现系统需求成为当时的重要议题。比如,在CAP之前研究者就已经发现低延迟和顺序一致性不可能同时被满足。
2000年,Eric Brewer教授在PODC的研讨会上提出了一个猜想:一致性、可用性和分区容错性三者无法在分布式系统中被同时满足,并且最多只能满足其中两个!这个猜想首次把一致性、可用性和分区容错三个因素提炼出来作为系统设计的重要特征,断言用此三者可以划分所有的分布式系统,并指明这三个特征之间的不可能性关系。Brewer猜想比单纯的“低延迟和顺序一致性不能被同时满足”的结论更具体,对实际系统的构建也更具有可操作性!Brewer教授当时想象的分布式场景是webservice,一组websevrice后台运行着众多的server,对service的读写会反应到后台的server集群,并对CAP进行了定义,就是上面列出的定义。高可用、数据一致是很多系统设计的目标,但是分区又是不可避免的事情,CAP的出现仿佛是一盏明灯,它揭露了分布式系统的本质,并给出了设计的准则,而这正是1985年以来人们正在寻找的东西!所以CAP在当时的影响力是非常大的!
2002年,Lynch与其他人证明了Brewer猜想,从而把CAP上升为一个定理。
 
这么一帆风顺吗?直至今日,对CAP理论的质疑声不断
 
就在这些理论被踢出来,大家觉得终于对分布式系统设计有了指导原则的时候,有些工程师和研究者就对CAP提出了各种质疑,纷纷有用反例证明着CAP在各种场合不适用性,同时挑战着Lynch的证明结果!你是否看了CAP的概念定义后还是感觉很模糊?如果是,你并不孤独,有很多人都是如此!CAP没有考虑不同的基础架构、不同的应用场景、不同的网络基础和用户需求,而C、A、P在这些不同场景中的含义可能完全不同,这种无视差异化的定义导致了非常大的概念模糊,同时也变成CAP被质疑的源头!其中,这些质疑主要集中在以下几个方面:
  • 概念模糊混乱,废话一堆,不能作为定理
  • 不适用于数据库事务架构
  • 应该构建不可变模型避免CAP的复杂性
  • 分区容错概念有误导

 
其实,搞了半天,我也不是很清晰这些高大上的推论和证明,也不是我们该操心的,因为CAP理论的提出者和证明者也在后续对这些质疑进行了相应的“回击”!
 
回击和解释
 
面对大量的质疑,Brewer和Lynch终于坐不住了,因此两人纷纷出来澄清。Brewer于2012年重申”3个中的2个“这个表述是不准确的,在某些分区极少发生的情况下,三者能顺畅地在一起配合,而且CAP不仅仅是发生在整个系统中,可能是发生在某个子系统或系统的某个阶段。
Lynch也在10年后的2012年重写了论文,缩小CAP适用的定义,消除质疑的场景,展示了CAP在非单一一致性结果下的广阔的研究结果!并顺便暗示CAP定理依旧正确!
 
多么精彩的“撕逼”过程!但是对我们来说,真正有意义的还是CAP理论本身。
 
我们该如何看待CAP理论本身?
 
首先肯定的是,CAP并不适合作为一个适应任何场景的定理,它的正确性更加适合基于原子读写的NoSQL场景。质疑虽然很多,但很多质疑者只是偷欢概念,并没有解决各个因素之间的取舍问题。而无论如何C、A、P这个三个概念始终存在任何分布式系统,只是不同的模型会对其有不同的呈现,可能某些场景对三者之间的关系敏感,而另一些不敏感。就像Lynch所说,现在分布式系统有很多特性,比如扩展性、优雅降级等,随着时间的发展,或许这些也会被纳入研究范畴,而作为开发者,这都是我们需要考虑的问题,而不仅是CAP三者!
 
对CAP三者的选择
 
当处理CAP的问题时,你会有几个选择。最明显的是:


 
1.(CA)放弃Partition Tolerance:
如果你想避免partition问题发生,你就必须要阻止其发生。一种做法是将所有的东西(与事务相关的)都放到一台机器上。或者放在像rack这类的atomically-failling单元上。无法100%地保证,因为还是有可能部分失败,但你不太可能碰到由partition问题带来的负面效果。当然,这个选择会严重影响scale限制。

2.(CP)放弃Availability:
相对于放弃partition tolerance来说,其反面就是放弃availability。一旦遇到partition 事件,受影响的服务需要等待数据一致,因此在等待期间就无法对外提供服务。在多个节点上控制这一点会相当复杂,而且恢复的节点需要处理逻辑,以便平滑地返回服务状态。

3.(AP)放弃Consistency:
或者如同Werner Vogels所提倡的,接受事情会变得“最终一致(Eventually Consistent)”(2008年12月更新)。Vogels的文章值得一读。他比我在这里讨论了更多的操作方面的细节。许多的不一致性并不比你想的需要更多的工作(意味着持续的consistency或许并不是我们所需要的)。在购书的例子中,如果一本库存的书,接到了2个订单,第二个就会成为备份订单。只要告知客户这种情况(请记住这是一种罕见的情况),也许每个人都会高兴的。
 


 
总结
 
在Consistency, Availability和Partition-tolerance中,你只能保证2点,这是确实的,并且已经被这个星球上最成功的网站证实了。如果对网站是有效的,我看不出在企业环境中,在日常的工作中,不考虑同样的折衷设计的理由。当然,CAP理论也只是对我们的分布式系统设计起到一个指导性的作用,我们在设计系统时,要考虑的方面也绝非只有这三个方面,正如上文所提到的,扩展性、降级等也是我们需要考虑的内容,所有,只有结合实际的业务需求和使用场景,才能设计出更加合适的系统。
 
参考资料:
1、http://blog.csdn.net/chen77716/article/details/30635543
2、http://blog.sina.com.cn/s/blog_493a8455010161hi.html
 

0 个评论

要回复文章请先登录注册