CAP 理论在互联网界有着广泛的知名度,知识稍微宽泛一点的工程师都会将其作为衡量系统设计的准则。大家都非常清楚地理解了 CAP:任何分布式系统在可用性、一致性、分区容错性方面,不能兼得,最多只能得其二,因此,任何分布式系统的设计只是在三者中的不同取舍而已。
事实上,让人吃惊的是,CAP 在国外的影响力完全不如所想,相反还伴随着诸多的争论。下面我们系统地阐述一下 CAP 的来龙去脉。
1. CAP 的历史
1985 年 Lynch 证明了异步通信中不存在任何一致性的分布式算法(FLP Impossibility)的同时,人们就开始寻找分布式系统设计的各种因素。一致性算法既然不存在,但若能找到一些设计因素,并进行适当的取舍以最大限度满足实现系统需求成为当时的重要议题。比如,在 CAP 之前研究者就已经发现低延迟和顺序一致性不可能同时被满足【8】。
2000 年,Eric Brewer 教授在 PODC 的研讨会上提出了一个猜想:一致性、可用性和分区容错性三者无法在分布式系统中被同时满足,并且最多只能满足其中两个!
这个猜想首次把一致性、可用性和分区容错三个因素提炼出来作为系统设计的重要特征,断言用此三者可以划分所有的分布式系统,并指明这三个特征之间的不可能性关系。Brewer 猜想比单纯的'低延迟和顺序一致性不能被同时满足'的结论更具体,对实际系统的构建也更具有可操作性!
Brewer 教授当时想象的分布式场景是 Web Service,一组 Web Service 后台运行着众多的 Server,对 Service 的读写会反应到后台的 Server 集群,并对 CAP 进行了定义:
- C(一致性):所有的节点上的数据时刻保持同步
- A(可用性):每个请求都能接受到一个响应,无论响应成功或失败
- P(分区容错):系统应该能持续提供服务,即使系统内部有消息丢失(分区)
高可用、数据一致是很多系统设计的目标,但是分区又是不可避免的事情:
- CA without P:如果不要求 P(不允许分区),则 C(强一致性)和 A(可用性)是可以保证的。但其实分区不是你想不想的问题,而是始终会存在,因此 CA 的系统更多的是允许分区后各子系统依然保持 CA。
- CP without A:如果不要求 A(可用),相当于每个请求都需要在 Server 之间强一致,而 P(分区)会导致同步时间无限延长,如此 CP 也是可以保证的。很多传统的数据库分布式事务都属于这种模式。
- AP without C:要高可用并允许分区,则需放弃一致性。一旦分区发生,节点之间可能会失去联系,为了高可用,每个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。现在众多的 NoSQL 都属于此类。
CAP 的出现仿佛是一盏明灯,它揭露了分布式系统的本质,并给出了设计的准则,而这正是 1985 年以来人们正在寻找的东西!所以 CAP 在当时的影响力是非常大的!
2. CAP 被上升为定理
2002 年,Lynch 与其他人证明了 Brewer 猜想,从而把 CAP 上升为一个定理【2】。但是,她只是证明了 CAP 三者不可能同时满足,并没有证明任意二者都可满足的问题,所以,该证明被认为是一个收窄的结果。
Lynch 的证明相对比较简单:采用反正法,如果三者可同时满足,则因为允许 P 的存在,一定存在 Server 之间的丢包,如此则不能保证 C,证明简洁而严谨。
在该证明中,对 CAP 的定义进行了更明确的声明【2】:
- C:一致性被称为原子对象,任何的读写都应该看起来是'原子'的,或串行的。写后面的读一定能读到前面写的内容。所有的读写请求都好像被全局排序。
- A:对任何非失败节点都应该在有限时间内给出请求的回应。(请求的可终止性)
- P:允许节点之间丢失任意多的消息,当网络分区发生时,节点之间的消息可能会完全丢失
该定义比 Brewer 提出的概念清晰了很多,也显得更加正式化!
3. 前所未有的质疑
当国内工程师对 CAP 痴迷的时候,国外的工程师和研究者对 CAP 提出了各种质疑,纷纷有用反例证明着 CAP 在各种场合不适用性,同时挑战着 Lynch 的证明结果!
纵观这些质疑,基本都是拿着一个非常具体的系统,用 CAP 的理论去套,最后发现要么 CAP 不能 Cover 所有的场景,要么是 CAP 的定义非常模糊,导致自相矛盾!一句话,把 CAP 接地气是非常困难的!
你是否看了 CAP 的概念定义后还是感觉很模糊?如果是,你并不孤独,有很多人都是如此!
CAP 没有考虑不同的基础架构、不同的应用场景、不同的网络基础和用户需求,而 C、A、P 在这些不同场景中的含义可能完全不同,这种无视差异化的定义导致了非常大的概念模糊,同时也变成 CAP 被质疑的源头!
3.1 质疑 1:概念混乱,废话一堆,不能作为定理
在论文【4】中,作者对 CAP 发起了强烈的挑战,强烈谴责了 CAP 模糊不一致的概念:
- 在 CA 中的 C 代表的是本地一致性;CP 中的代表的是全局一致性,AP 中直接没有 C;这些 C 的含义在不同的场景根本就不同
- 终端用户 agent 该不该引入到 CAP 中?CAP 到底是说一个 agent 的多次更新,还是多个用户的一次更新?没有 agent 参与的系统谈什么一致性?

