跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
编程语言java算法

CAP 理论:分布式系统设计准则与争议解析

CAP 理论表明分布式系统无法同时满足一致性、可用性和分区容错性,最多只能满足其中两个。文章追溯了 CAP 从 Brewer 猜想到 Lynch 证明的历程,详细阐述了 C、A、P 的定义及其在不同场景下的含义差异。针对国外研究者提出的概念模糊、不适用于数据库事务等质疑,文中整理了 Brewer 和 Lynch 的澄清回应,强调 CAP 更适用于原子读写场景。最终建议开发者结合具体架构需求,在一致性与可用性间灵活取舍,并关注扩展性等更多系统特性。

极客零度发布于 2025/2/13更新于 2026/4/231 浏览
CAP 理论:分布式系统设计准则与争议解析

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 模糊不一致的概念:

  1. 在 CA 中的 C 代表的是本地一致性;CP 中的代表的是全局一致性,AP 中直接没有 C;这些 C 的含义在不同的场景根本就不同
  2. 终端用户 agent 该不该引入到 CAP 中?CAP 到底是说一个 agent 的多次更新,还是多个用户的一次更新?没有 agent 参与的系统谈什么一致性?
  3. 如果分区发生在系统内部(水平分区),对 agent 而言并没有影响;若分区发生在 agent 与系统间(垂直分区),这种情况对 DNS 系统架构的可用性根本没有任何影响;但对银行事务架构却有巨大影响。也就是说,可用性、分区容错,是两个相关且无法独立切分的概念

一句话:CAP 说了一些永远不存在的废话!作为一个严格的数学定理,一定要概念清晰并且可自证明,CAP 显然不具备这个条件,并声称'绝不承认其为一个定理'!

【4】的作者对相对论有相当的理解,从相对论来看,每个节点都只知道自己的结果,永远无法得知其他节点的情况,系统整体是否一致我怎么会知道?

并且作者对一致性、可用性归结为一个非常深刻的见解:一切都是时间视图!多长时间返回结果算可用?多长时间返回认为不可用?多长时间数据同步算一致?因此,一切的本质是时间!

根据时间特性和相对论,作者提出了一个独创的 promise 系统模型,每个节点都对自己的行为在有限时间内进行承诺,其他节点根据这个承诺和自己的状态决定本地如何处理...

作者还上传了自己的笔记拍照,我大体看了下,基本上是构建了一个基于时间同步的有限状态机,实际上 Lynch 早就证明,在同步环境的一致性是可以达到的!

3.2 质疑 2:不适用于数据库事务架构

【6】的作者,把详细地列举了分布式事务中可能的分区情况,比如说应用因为更新一些错误的数据而导致失败,此时无论使用什么样的高可用方案都是徒劳,因为数据发生了无法修正错误!作者还列举了其他一些情况,虽然分区发生但无法保持高可用。这就说明了 CAP 并不能不被用来完全解释数据库事务架构!

作者还建议,应该放弃分区容错,因为在局域网中分区很少发生;而在广域网中,有各种备选方案,导致实际上的分区也较少发生。

3.3 质疑 3:应该构建不可变模型避免 CAP 的复杂性

【7】的文章标题就是锤死 CAP,作者对 CAP 的不屑溢于言表!

作者认为 CAP 的困境在于允许数据变更,每次变更就得数据同步,保持一致性,这样系统非常复杂。

他认为数据就是客观存在的,不可变,只能增、查。传统的 CURD 变为 CR。这个概念非常类似 Cassandra 中的顺序写的概念,任何的变更都是增加记录。通过对所有记录的操作进行合并,从而得到最终记录。

因此,作者认为任何的数据模型都应该抽象为:Query=Function(all data),任何的数据试图都是查询,查询是对全体数据施加了某个函数的结果。这个定义清晰简单,完全抛弃了 CAP 那些繁琐而又模糊的语义。因为每次操作都是对所有数据进行全局计算,也就没有了一致性问题!

有这样的系统吗?有,Hadoop 便是!作者认为,Hadoop 的 HDFS 只支持数据增加,而 MapReduce 却进行全局计算,完美地符合了他对数据处理的期望!

Hadoop 也存在某个节点数据丢失的问题,但随着流式计算,丢失的数据终究会随着系统的正常而被最终合并,因此数据最终是一致的。

Hadoop 不能进行实时计算咋办?作者又构建了一套基于 Cassandra 和 ElephantDB 的实时数据处理系统。。。。搞的无比复杂!

3.4 质疑 4:分区容错概念有误导

【5】的作者主要质疑【6】,但比较清晰得揭露了 CAP 的概念之间的模糊。

【5】认为,可用性和一致性是分布式系统的属性,而分区却是网络的一个属性。不能再问题发生时是否选择要不要分区,而是应该在分区既定的情况下选择要一致性还是可用性。网络分区会发生在两种情况:

  • 交换机失败,导致网络发生【6】中描述的情况,网络被分成几个子网
  • 机器延迟或死机,导致某些 server 失去联系

【6】中所谓的分区就是情况 1,每个独立的子网还能正常运作,作者认为这种分区条件非常苛刻,更倾向于认为这只是分区可用性的一种度量方式(发给每个子网的请求都有正确的 response)。

而实际上,因为机器原因发生的分区的情况更常见一些,如果'很多'机器都发生故障,系统会因为一个'多数派'的丢失而导致不可用(比如,因为多数不存在,最新的读可能无法读取到上一次的写)。一句话:分区也同时蕴涵着不可用,这两个概念之间存在重叠。

作者认为,CAP 比较合理的表达方式应该是:在一个允许网络发生故障的系统中,该选择一致性还是可用性?

当系统的机器数量持续增加时,一致性会加剧时延,维护一致性的成本会非常之高,因此我们基本就剩下一种选择:在允许网络失败的系统中,更多地是选择可用性。而 Zookeeper、Hadoop 之所以选择一致性,是因为这些系统多数是有在同一集群的少数节点构成!

【5】的作者其实间接地否认了'3 个中同时满足 2 个'这样的误解,而是从更深层次探讨了 CAP 的本质,但并没有试图推翻 CAP。

4. 对质疑的回应

面对大量的质疑,Brewer 和 Lynch 终于坐不住了,因此两人纷纷出来澄清:

Brewer 于 2012 年重申【1】:

  • '3 个中的 2 个'这个表述是不准确的,在某些分区极少发生的情况下,三者能顺畅地在一起配合
  • CAP 不仅仅是发生在整个系统中,可能是发生在某个子系统或系统的某个阶段

该声明并不否认像质疑 3 那种三个因素协同工作的情况,并把 CAP 应用在一些更细粒度的场景中。

Lynch 也在 10 年后的 2012 年重写了论文【3】,该论文主要做了几件事:

  • 把 CAP 理论的证明局限在原子读写的场景,并申明不支持数据库事务之类的场景
  • 一致性场景不会引入用户 agent,只是发生在后台集群之内
  • 把分区容错归结为一个对网络环境的陈述,而非之前一个独立条件。这实际上就是更加明确了概念
  • 引入了活性 (liveness) 和安全属性 (safety),在一个更抽象的概念下研究分布式系统,并认为 CAP 是活性与安全熟悉之间权衡的一个特例。其中的一致性属于 liveness,可用性属于 safety
  • 把 CAP 的研究推到一个更广阔的空间:网络存在同步、部分同步;一致性性的结果也从仅存在一个到存在 N 个(部分一致);引入了通信周期 round,并引用了其他论文,给出了为了保证 N 个一致性结果,至少需要通信的 round 数。也介绍了其他人的一些成果,这些成果分别都对 CAP 的某一个方面做出了特殊的贡献!

其实 Lynch 的论文主要就是两件事:缩小 CAP 适用的定义,消除质疑的场景;展示了 CAP 在非单一一致性结果下的广阔的研究结果!并顺便暗示 CAP 定理依旧正确!

从此论文还是可以看出,Lynch 的功力高出其他质疑者好多!

5. 该如何看待 CAP?

首先肯定的是,CAP 并不适合再作为一个适应任何场景的定理,它的正确性更加适合基于原子读写的 NoSQL 场景。质疑虽然很多,但很多质疑者只是偷换概念,并没有解决各个因素之间的取舍问题。而无论如何 C、A、P 这个三个概念始终存在任何分布式系统,只是不同的模型会对其有不同的呈现,可能某些场景对三者之间的关系敏感,而另一些不敏感。在所有的质疑当中,质疑 4 是分析的比较中肯的,其清晰的概念分析该让我们对 CAP 有更深入的理解!

就像 Lynch 所说,现在分布式系统有很多特性,比如扩展性、优雅降级等,虽然时间的发展,或许这些也会被纳入研究范畴,而作为开发者,这都是我们需要考虑的问题,而不仅是 CAP 三者!

6. 参考资料

【1】http://en.wikipedia.org/wiki/Cap_theorem 【2】http://lpd.epfl.ch/sgilbert/pubs/BrewersConjecture-SigAct.pdf 【3】http://groups.csail.mit.edu/tds/papers/Gilbert/Brewer2.pdf 【4】http://markburgess.org/blog_cap.html 【5】http://blog.cloudera.com/blog/2010/04/cap-confusion-problems-with-partition-tolerance/ 【6】http://cacm.acm.org/blogs/blog-cacm/83396-errors-in-database-systems-eventual-consistency-and-the-cap-theorem/fulltext 【7】http://nathanmarz.com/blog/how-to-beat-the-cap-theorem.html 【8】http://highscalability.com/blog/2011/11/23/paper-dont-settle-for-eventual-scalable-causal-consistency-f.html

目录

  1. 1. CAP 的历史
  2. 2. CAP 被上升为定理
  3. 3. 前所未有的质疑
  4. 3.1 质疑 1:概念混乱,废话一堆,不能作为定理
  5. 3.2 质疑 2:不适用于数据库事务架构
  6. 3.3 质疑 3:应该构建不可变模型避免 CAP 的复杂性
  7. 3.4 质疑 4:分区容错概念有误导
  8. 4. 对质疑的回应
  9. 5. 该如何看待 CAP?
  10. 6. 参考资料
  • 💰 8折买阿里云服务器限时8折了解详情
  • 💰 8折买阿里云服务器限时8折购买
  • 🦞 5分钟部署阿里云小龙虾了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog

更多推荐文章

查看全部
  • 大语言模型应用指南:Gorilla
  • 职场与软件开发中的细节内涵及提升
  • 程序员如何入局 AI 大模型及职业发展路径
  • LeetCode 第 5 题:最长回文子串
  • Python 自学项目资源整理
  • 提升 SQL 技能的 7 个最佳练习平台
  • 基于SpringBoot的网上租赁系统设计与实现
  • C# 使用 Log4Net 配置日志
  • Java 企业人事工资管理系统设计与实现
  • Linux LVM 磁盘管理工具详解:物理卷、卷组与逻辑卷操作
  • 软件设计各个模块分析
  • 交换瓶子问题 Java 最小交换次数解法
  • Java Cookie 技术原理与应用
  • CopyOnWriteArrayList 源码解析
  • Python 学习后如何找工作及就业方向分析
  • Windows 环境下如何将本地代码推送到 Git 远程仓库
  • Vue 中使用 Less 样式预处理
  • 大语言模型框架-Megatron-LM 源码分析
  • CSS 子元素选择器
  • Webpack Loader 一览表

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online