1976年6月4号,周5,在远离音乐会大厅的一个楼上的房间内,在位于Manchester的Lesser Free Trade Hall ,Sex Pistols 乐队(注:Sex Pistols的经理人Malcolm McLaren 2010.4.8去世)開始了他们的第一次演出(gig, 注:规模太小称不上演唱会 )。关于当晚谁出席了那场演出有些混乱,部分是由于6周后的还有一场音乐会,但最基本的还是由于,这场演出被觉得是永久改变西方音乐文化 的一场演出。这场演出是如此的重要且富有象征意义,以至于David Nolan写了一本书:《我发誓我在那里:那场改变了世界的演出 》,对那些声称自己看过那场演出的人做出推断。由于6月4号被觉得是punk摇滚的開始。
在这之前(大约是在1971年左右)曾有一些protopunk 乐队,比如New York Dolls 和Velet Underground ,但从音乐民俗学来说,是Sex Pistals开启了这场革命,在这场运动中驱动了Buzzcocks 乐队的吉他,The Smiths 乐队哀怨的哭诉,The Fall 乐队的电子切音,Joy Division 和Simply Red 乐队华丽的升调(我猜你不了解全部的含义)(注:我缺乏摇滚方面的知识,这部分翻的不是非常惬意,好在不影响大局,有punk摇滚知识的同学能够提供帮助 )
2000年7月19号,周三,对主流文化来说并不(象前者一样)具有相同的重要性,但这个日子对互联网公司来说,和25年Sex Pistols对音乐所做的一样,具有相同的影响。这就是Eric Brewer 在ACM研讨会上关于分布式计算的原则 (Principles of Distributed Computing)所做的开题演讲 (keynote speech)。
Sex Pistols向同一时候代的人展示了差点儿无限制的狂躁远比学院派的结构主义重要的多,给不论什么人3根弦以及一些许可就能够组建一支乐队。Eric Brewer,在那时被称为Brewer猜想,觉得当应用系统变得越来越web化,应当放弃对数据一致性(data consistency)的担忧,由于要想获得这样的新的分布式系统的高可用性(high availability),确保数据一致性是我们无法做到的,这样给予不论什么人3台server和一双关注客户体验的眼睛就能够建立一家互联网公司。Brewer的信徒(当天就有的和后来皈依的)包含像Amazon , EBay 和Twitter 这类公司
2年后,2002年,麻省理工(MIT)的Seth Gilbert 和Nancy Lynch ,理论上证明 了Brewer猜想是正确的,就此Brewer定理(Theorem)诞生了。
那么究竟Brewer的定理是什么,为何它足以和1976年Manchester的punk演出媲美?
Brewer 在2000年的演讲是基于他在UC Berkley的理论工作以及主持Inktomi (期间)的观察,是通过数年前Brewer和其它人,在怎样构建高伸缩性系统(highly scalable system)时所做出的各种折衷方案的讨论(比如:SOSP(Symposium on Operating System Principles)的1997年的Cluster-Based Scalable Network Service 和1999年的Harvest, yield, and scalable tolerant system )就像其它的很多思想,因此这个演讲的内容并非全新的,它是很多聪明人的共同成果(我确信Brewer会非常快说明这一点)。
Brewer觉得在分布式的环境下设计和部署系统时,有3个核心的系统需求 (systemic requirements),以一种特殊的关系存在。(他主要是谈论Web类的应用,但现在许多的公司业务是多网站/多国家的,因此该理论相同适用于你的数据中心/LAN/WAN的设计)
这3个核心的需求是:Consistency ,Availability 和Partition Tolerance ,赋予了该理论另外一个名字 - CAP 。
要想将该理论和现实的联系起来,让我们举一个简单的样例:你想购买一套托尔斯泰 的《战争与和平 》,以便在明天開始的长假中有可读的东西。然而你最喜欢的网上书店仅仅有一本库存了。你进行搜索,确认书能够在你出发前送到,然后将书增加你的购物车。接着你想起来另一些其它的东西要买,所以继续浏览站点(你是否在站点仅仅买一件东西?当然要充分利用包裹的费用了)。但当你查看某个防晒霜的客户反馈时,国内某个地方的某个人,进入站点,将那本书增加到自己的购物车,然后直接付款(他们急需解决桌子摇晃的问题,当中一条桌脚比其它的短的多)。
一旦開始将数据和逻辑分布在不同的节点上,就有形成partition的风险。假定网线被切断,partition就形成了,节点A无法和节点B通讯。因为Web提供的这样的分布式能力,暂时的partition是一个常见的情况,如之前说所的,在全球化的有多个数据中心的公司中这并不罕见。
Gilbert 和Lynch是这样定义partition tolerance的
除了整个网络的故障外,其它的故障(集)都不能导致整个系统无法正确响应。(No set of failures less than total network failure is allowed to cause the system to respond incorrectly)
请注意Brewer的凝视,单节点partition就等同于servercrash,由于假设无法连接它,那它就和不存在一样。
CAP定理在应用系统规模化时最有效。在低压力的情况下,小的延迟(以便数据库达到一致的状态)还不足以对整体的性能或用户体验造成影响。你所承担的负载分布,可能都是出于系统管理的原因。?
但随着活动的添加,吞吐量的上限(pinch-points)将会限制增长并产生错误。必须等待网页的返回是一种情况,还有一种情况则是在你输入信用卡信息后遇到 “HTTP 500 java.lang.schrodinger.purchasingerror”,你就想知道你是否付了钱但无法得到东西,还是没付钱,或者这仅仅是交易中一个不重要的错误。谁知道呢?你不太可能继续下去,非常有可能到别的地方购物,或更有可能给银行打电话。
无论是那种情况对业务都没有优点。Amazon声称 每0.1秒的响应延迟都会导致1%的销售减少。Google说 他们注意到0.5秒的延迟会使流量降低15%。
我之前 曾就scalability写过一些东西,不想在这里反复,仅仅想指出2点:第一点是,解决scale问题看起来是一个架构方面的问题,但最初的讨论却不是,而是业务决策。我已经非常厌倦听到技术人员说,由于当前的流量,这样或那样的方案不能用。并非说技术人员错了,通常他们讲的非常正确,是由于从一開始所限定的scale 隐含地做了revenue决策-这一问题应该在业务分析时明白地决定下来。
第二点是,一旦你開始讨论怎样scale业务系统,大致会落到2种意识形态阵营中:数据库派和非数据库派。
对于数据库派来说,毫无疑问,钟爱数据库技术,并倾向于谈论optimistic locking 和sharding 这类的东西来解决scale问题,并将数据库作为系统的核心。
非数据库派会倾向于尽可能多的在数据库环境(避免关系世界)之外管理数据以解决scale问题。
我觉得,能够公平地说,前一派人对CAP定理的热情肯定不如后一派(虽然他们在讨论定理 )。这是由于,假设你必须在consistency,availability,partition tolerance三者中放弃一个,大多数会选择放弃consistency,而consistency是数据库存在的理由。(选择的)逻辑,无疑,是availability和partition tolerance可以使你赖以赚钱的系统生存下去,而不一致性感觉好像是你可以用好的设计来解决的问题。
和IT中的其它事情一样,这不是非黑即白的问题。Eric Brewer在其PODC演讲的第13页slide中,当比較ACID和其非正式的相应物的BASE 时,甚至说“我觉得这是一个系列(spectrum)”(注:这里光谱有一个系列的含义,是指ACID和BASE是不正确立的)。假设你对这个主题感兴趣(有些超出我在这里讨论的范围了),你能够从一篇叫做,“Design and Evaluation of a Continuous Consistency Model for Replicated Service ”的论文開始,该文由Haifeng Yu和Amin Vahdat 编写。大家不能够将CAP解读为暗示数据库的消亡。
虽然这样,两方都认同scale的解决之道是分布式的并行计算,而不是以前觉得的超级计算机。90年代中期进行的Network of Workstations 项目受到了Eric Brewer的影响,并终于导致了CAP定理的诞生,由于他在一个关于Inktomi and the Internet Bubble 的介绍中说到,答案总是并行处理:
假设不通过并行的方式,你就没有机会,在合适的时间内解决这个问题。和其它很多事情一样。假设是个非常大的项目,会须要非常多人来完毕它。因此,假设想建造一个桥梁,就须要非常多建筑工人。这就是并行处理。因此问题会演变为“怎样将并行处理和internet结合在一起”
这里有一个简单的图片证明,由于我发现用图片会比較好理解。多数情况下我使用和Gilber 和Lynch同样的术语,以便和他们的论文联系起来。
上图显示了网络中的两个节点N1,N2。他们共享同一数据V(库存中《战争与和平》的数量),其值为V0。N1上有一个算法A,我们能够觉得A是安全,无bug,可预測和可靠的。N2上有一个相似的算法B。在这个样例中,A写入V的新值而B读取V的值。
正常情况下(sunny-day scenario),步骤例如以下:(1)A写入新的V值,我们称作v1。(2)N1发送信息给N2,更新V的值。(3)如今B读取的V值将会是V1。
假设网络断开(partions)(意味着从N1无法发送信息到N2)那么在第3步的时候,N2就会包括一个步一致的V值。
希望看上去非常明确。即使将其scale到几百个事务(transaction)中,这也会成为一个大问题。假设M是一个异步消息,那么N1无法知道N2是否收到了消息。即使M是保证能发送的(guaranteed delivery),N1也无法知道是否消息由于partition事件的发生而延迟,或N2上的其它故障而延迟。即使将M作为同步(synchronous)信息也不能解决这个问题,由于那将会使得N1上A的写操作和N1到N2的更新事件成为一个原子操作(atomic operation),而这将导致相同的等待问题,该问题我们已经讨论过(或更糟)。Gilbert 和Lynch已经证明,使用其它的变种方式,即使是部分同步模型(每一个节点上使用安排好的时钟)也无法保证原子性(atomicity)。
因此,CAP告诉我们,假设想让A和B是高可用(highly available)的(比如,以最小的延迟(latency)提供服务)而且想让全部的N1到Nn(n的值可以是数百甚至是上千)的节点可以冗余网络的partitions(丢失信息,无法传递信息,硬件无法提供服务,处理失败),那么有时我们就得面临这种情况:某些节点觉得V的值是V0(一本《战争与和平》的库存)而其它节点会觉得V的值是V1(《战争与和平》的库存为0)
我们都希望全部的事情是结构化的,一致的且和谐的,就像70年代早期的prog rock 乐队,但我们面临的是一些punk风格的混乱。其实,虽然有可能会吓到我们的祖母,但一旦你了解了它就还OK,由于2者能够很愉快地在一起工作。
让我们从事务(transactional)的角度高速分析一下。
假设我们有个事务(比如:一组环绕着persistent数据项V的工作单元)a,a1是写操作,a2是读操作。在一个local的系统中,能够利用数据库中的简单锁(simple locking)的机制方便地处理,隔离(isolating)a2中的读操作,直到a1的写成功完毕。然而,在分布式的模型中,须要考虑到N1和N2节点,中间的消息同步也要完毕才行。除非我们能够控制a2何时发生,我们永远无法保证a2能够读到a1写入的数据。全部增加控制的方法(堵塞,隔离,中央化的管理,等等)会要么影响partition tolerance,要么影响a1(A)和a2(B)的可用性。
当处理CAP的问题时,你会有几个选择。最明显的是:
如您所指出的,术语BASE第一次出现是在1997年的SOSP文章中。那一年,我和我的学生在他们的办公室中,一起造了这个词。我承认这有些人为的因素,但ACID也是一样的--远超人们所能意识到的,所以我们人为还行。Jim Gray和我讨论了这些缩写,他欣然认可ACID也有些扭曲(stretch)– A和D(的概念)有相当多的反复部分,C至多也是含糊不清的。但这对术语暗示了一系列的理念(idea of spectrum),这是PODC演讲中的一个重要观点,你正确地指出了这一点。
EBay的Dan Pritchett有一篇关于BASE的非常棒的介绍 (presentation)。
在Consistency, Availability和Partition-tolerance中,你仅仅能保证2点,这是确实的,而且已经被这个星球上最成功的站点证实了。假设对站点是有效的,我看不出在企业环境中,在日常的工作中,不考虑相同的折衷设计的理由。假设业务方面明白表明不须要上规模(scale)那好,有简单的解决方式,但这是值得讨论的。在不论什么情况下,这些讨论都是针对特定操作的适合的设计,而不是庐山(注:shebang取意译)全貌。正如Brewer在其邮件中所说的:“唯一的我能够增加的是同一服务的不同部分能够选择这一系列(spectrum)中的不同的点”有时,不管scale的代价怎样,你绝对须要一致性 ,由于缺少它的风险太大了。
这些天,我说得有些过,说Amazon和EBay没有scalability问题,我觉得他们的确有这类问题,但他们如今有办法解决该问题。这也是为何他们能够自由讨论这些问题的解决办法。不论他们如今是何规模(结合他们早就发布的数字)仅仅会越来越大。一旦规模上来,你的问题就会转到(shift)诸如操作维护,监控,发布软件的更新等等 - 当然(这些问题)都非常难解决,但值得,尤其当你因此获得现金流(revenue stream)。