

一致性(Consistency)在CAP中是可线性化的意思(linearizability)。而这个是非常特殊(而且非常强)的一致性。尤其是虽然ACID中的C也是一致性(Consistency),但是和这里的一致性没有任何关系。我会在后面解释可线性化是什么意思。
可用性(Availability)在CAP中是定义为“每一个请求(request)如果被一个工作中的[数据库]节点收到,那一定要返回[非错误]的结果”。注意到,这里一部分节点可以处理这个请求是不充分的。任意一个工作中的节点都要可以处理这个请求。所以很多自称“高度可用”的系统通常并没有满足这里的可用性的定义。
分区容错(Partition Tolerance)基本上就是说通信是在异步的网络中。信息是可能延迟送达或者被丢失的。互联网还有我们所有的数据中心都有这个属性。所以我们在这件事上并没有选择。
CAP系统的模型是一个只能读写单个数据的寄存器。这就是全部。CAP没有提到任何关于关系到多个事物(object)的事务(transaction)。他们根本就不在这个定理的范围之内,除非你可以把这些问题约化到一个单个寄存器的问题。
CAP定理只考虑了网络分区这一种故障情况(比如节点们还在运行,但是他们之间的网络已经不工作了)。这种故障绝对会发生,但是这不是唯一会出故障的地方。节点可以整个崩溃(crash)或者重启,你可能没有足够的磁盘空间,你可能会遇到一个软件故障(bug),等等。在建分布式系统的时候,你需要考虑到更多得多的问题。如果太关注CAP就容易导致忽略了其他重要的问题。
还有CAP根本没有提到延迟(latency)。而常常人们其实对关心延迟比可用性更多。事实上,满足CAP可用性的系统可以花任意长的时间来回复一个请求,而且同时保持可用性这个属性。我来冒险说一句,我猜如果你的系统要花两分钟来加载一个页面,你的用户是不会称它是“可用的”。




你的应用还是被允许写到数据库,所以两边的数据库还是完全可用的。但是一旦两个数据库之间的网络中断了,任何一个数据中心的写操作就不会在另一个数据中心出现。这就违反了可线性化(用之前的例子,Alice可能链接到了一号数据中心,而Bob连接到了二号数据中心)。
如果你不想失去可线性化,你就必须保证你的读写操作都在同一个数据中心,你可能叫这它leader。另一个数据中心,因为网络故障不能被更新,就必须停止接收读写操作,直到网络恢复,两边数据库又同步了之后。所以虽然非leader的数据库在正常运行着,但是他却不能处理请求,这就违反了CAP的可用性定义。



在同一个软件内,你可能有多个一致性属性的选择
很多系统在CAP的定义下,既不是一致也不可用。然而我从来没有听到别人称这些系统为"P",可能是因为这样不太好看。但这并不差,他很可能是完全合理的设计,他只是不在CP/AP这两个分类中。
虽然大部分软件都不在CP/AP这两类中,但人们还是强行把软件分为这两类。这就导致了,为了适用,不可避免地改变对“一致性”或者“可用性”的定义。不幸的是,如果用词的定义改变了,CAP定理自己也不适用了,那CP/AP区分也就完全没有意义了。
把系统分为这两类,导致了很多细节被忽略。在考虑分布式系统设计的时候,会有很多关于容错,延迟,简单模型,运行成本,等等的考虑。把那么多细节编码到一个比特的信息,显然是不可能的。比如说虽然ZooKeeper有一个AP的只读模式,但这个模式也提供对所有写操作的total ordering。这比Riak或者Cassandra这些AP系统提供的保障要强得多。所以简单地把他们都归为AP一个类别就显得很不合理。
甚至Eric Brewer承认CAP是一个容易误导人的而且过于简化的模型。在2000年,CAP的意义在于让大家开始讨论关于分布式系统的取舍。他在这方面做得很好。但是他不是用来作为一个正式的突破性的结果,也不是一个严格的数据系统的分类方式。15年之后,我们已经有了多得多的有不一样一致性和容错模型的系统。CAP已经完成了他自己的使命,现在是时候不要在纠结了。

一个很好的起点就是Doug Terry的论文。其中他用棒球来解释了各种不一样的最终一致性[9]。可读性很强,而且就算对像我这样不是美国人而且完全不懂棒球也解释的很清晰。
如果你对transaction的isolation模型有兴趣(这和分布式系统的一致性不一样,但是相关),我的小项目Hermitage你可以看一下。
这篇论文[10]讨论了分布式系统的一致性和transaction的isolation以及可用性之间的关系。(这篇论文也描述了不同一致性之间的分级。Kyle Kingsbury很喜欢给别人讲这个[11]。

当你读到过这些了以后,你应该已经准备好深入阅读论文。我在这篇文章中加入了很多对文献的引用。去看一下,很多专家已经帮你把很多问题都已经解决了。
作为最后的手段,如果你不想读论文原文,我建议你看一下我的书[12]。这本书用通俗易懂的方式总结了大多数重要的思想。(你看,我已经竟可能的让这篇文章看上去不是用来推销我的书的。)
如果你想学跟多关于怎么正确使用ZooKeeper,Flavio Junqueira 还有 Benjamin Reed的书[13]是非常不错的。
https://www.somethingsimilar.com/2013/01/14/notes-on-distributed-systems-for-young-bloods/
http://www.the-paper-trail.org/page/cap-faq/
https://codahale.com/you-cant-sacrifice-partition-tolerance/
http://dataintensive.net/
https://mechanical-sympathy.blogspot.com/2011/07/memory-barriersfences.html
https://blog.the-pans.com/cap/www.allthingsdistributed.com/files/amazon-dynamo-sosp2007.pdf
http://basho.com/posts/technical/riaks-config-behaviors-part-3/
http://zookeeper.apache.org/doc/r3.4.6/zookeeperProgrammers.html#ch_zkGuarantees
https://www.microsoft.com/en-us/research/publication/replicated-data-consistency-explained-through-baseball/
https://blog.the-pans.com/cap/arxiv.org/pdf/1302.0309.pdf
https://aphyr.com/posts/322-call-me-maybe-mongodb-stale-reads
http://dataintensive.net/
http://shop.oreilly.com/product/0636920028901.do




