CAP 定理说,在一个发生网络分区(分区容忍性 P)的系统里,一致性 C 与可用性 A 只能保证一个,不可能两个同时成立。它不是一个需要你去信的声称,而是一个经证明的结论,作用是指明"当网络断了,你必须在给旧值和继续响应之间二选一"。本节先把定理说准,再讲清那个常被误解的边界。
先把 CAP 里的三件待办摆到桌面上:一致性、可用性、分区容忍。它们不是三个平级选项,而是"分区必然发生"的前提下,C 与 A 只能保一个的格局。你先把这张三角描出来,后面所有展开都只是给这三个角补充细节。
阅读完本节,你应当能够:
C 一致性:某次写入之后,任何一次读取必须读到这个最新值(或者读失败,但不能读到旧值)。A 可用性:非故障节点必须在合理时间内发出正常响应,哪怕返回的是旧数据。P 分区容忍性:集群里的节点因为网络故障被隔成几块(分区)时,系统仍然要继续工作。这三者里,P 是"网络总会断"带来的必然前提——因为它不由你决定。
设定一个小剧场:订单数据存了两个副本,节点 A 在华东、节点 B 在华南,两者之间的网络断开,形成两个孤立的区。这时一个下单请求落到 B 区,要把库存减一。选项摆开:
看到了吗,在网络分区的那一刻,你只能二选一。这正是 CAP 想表达的:只要有 P 这个前提在,C 与 A 在分区瞬间就是互斥的。而"不分区"时 C 与 A 当然可以同时满足,所以 CAP 的适用范围必须加上"发生分区时"这个限定。
下面这张 SVG 把 CAP 画成铁三角,也标出"分区发生"这个触发条件——只有在这个条件下,矛盾才真正摊上台面:

CAP 的结论来自一个简单的反证:若网络把集群劈成两个不连通的区,你想同时拿到 C 和 A——读写到两边的同一个 key。若两边都能立刻返回(A),其中一边必然没法确认另一边的写入(因为连不上),于是一边会返回旧值(破坏 C);若两边都坚持返回新值(C),其中一边因连不上而无法获知最新状态,只能挂起等待(破坏 A)。两条路都走不通,因此同时 C 和 A 无法成立。这个推演里没有任何假设的网络模型,是纯粹的逻辑必然,所以 CAP 被称为定理。
很多教材会把系统粗暴分成 CP 型和 AP 型,这是一种为了教学的简化。真实系统更常见的姿态是按需动态切换:分区不发生的时候,它完全可以同时在 C 和 A 上表现良好;分区一旦发生,才被迫在两者间站队。所以采访一个上线系统"你选了 CP 还是 AP"其实问得很粗糙——更准确的问题是"你网络分区时,牺牲的是哪头"。
| 选择 | 牺牲 | 适合场景 | 例举 |
|---|---|---|---|
| CP | 分区时先拒单,等网络恢复 | 财务、订单、余额,宁可错不可错付 | 银行核心、HBase |
| AP | 分区时先放行,补差异 | 社交、风控黑名单、读数可容忍 | Cassandra、Dynamo |
选 CP 的行业往往有一条底线:这笔账错了会出大问题,宁可那一刻接不了单也不能错。选 AP 的业务大多读多写少、对短暂读到旧值容忍度高,把"分区时还能接单"看得比"刚写完全被所有人立刻看到"更重要。实践中没有绝对的对错,只有"你的客户能容忍哪头坏"。
跟人聊 CAP 时,下面三句话十次有八次会说错,帮你提前拨正。
迷思一:"一上分布式,我就永远在 C 和 A 里做单选题。" 不对。CAP 成立的前提是"发生分区这一刻"。制度的反派是分区,不是分布式本身。平时网络好好的,系统完全可以在 C、A 上同时表现良好;只有网络把集群切成两半的那几秒,才被迫站队。所以别把"常态"描述成"每时每刻二选一"。
迷思二:"CP 系统就是平时也不可用。" 这是把"分区时不响应"夸大成"永远不响应"。CP 系统平时照常对外服务,只是把"分区时宁可短暂拒绝"写进了设计。它牺牲的是"分区瞬间能不能继续接单",而不是日常可用性。
迷思三:"AP 就是不要一致性。" 更准确的表达是"放弃分区瞬间的强一致"。AP 系统平时通常也有不错的一致性表现,只是它允许分区时先用旧值扛过去,等网络恢复再补对账。把"降一档"说成"全不要",是很多澄清的文章开篇就要先纠正的偏差。
把这三个迷思钉死,你对 CAP 的理解就从"背结论"升级成"懂边界"——也方便你下次遇到同事转发的一段话,一眼看出它哪句说得过头了。
聊 CAP 最容易在"分区到底指什么"上卡壳,用一张具体场景钉住它:你的集群铺在华东与华南,中间链路上的交换机坏了,两边的节点互相连不上——这一刻集群被劈成两个孤岛,这就是分区。注意分区不等于某台机器挂了:两台都好好活着,只是彼此断了联系。区分这两点很重要——机器挂了是"少了员",还能靠多数投票绕过去;分区是网络把队伍切成两半,两边都可能认为自己才是对的那一半,这才是 CAP 真正要对付的困局。想明白"分区≠宕机",你对 CAP 适用范围的把握就深了一层,也不会再把"给单台做冗余"误当成"解决分区"的办法。
CAP 告诉你"你得在 C 和 A 之间妥协",下一节 2.2 把妥协省下来的东西用到极致——BASE 原则明确告诉你,我可以不要强一致,但我保证最终一致,省下的可用性和性能该怎么花。