第一性问题:
当多个节点各自保存同一份数据副本,而节点之间的通信是不可靠的, 系统如何对外表现为"正确且可用的一个整体"?
分布式一致性问题的本质是一个物理约束下的系统行为选择问题:
不可靠的物理载体(通信可断、节点可崩)被要求兑现可靠的逻辑承诺(数据正确、服务可用)——一致性理论的全部工作,就是在这条无法消除的鸿沟上决定如何取舍。
所有后续理论(CAP / BASE / Lease)都只是对这一根本矛盾的不同抽象层回应。
这些抽象层构成一条上层约束倒逼下层回应的递进链:每一层划定边界,下一层在边界内做出选择,再下一层落地并兜底。
| 层次 | 理论 / 机制 | 回答的问题 | 与上层的关系 |
|---|---|---|---|
| 理论约束层 | CAP + FLP | 分区 / 异步下能保证什么 | 划定可能性边界 |
| 时间维度层 | PACELC | 无分区常态下如何取舍 | 补 CAP 的盲区 |
| 工程策略层 | CP / AP | 具体选哪种行为 | 在约束内决策 |
| 机制实现层 | Quorum / Lease / 复制协议 | 用什么落地 | 实现策略选择 |
| 治理修正层 | 幂等 / 冲突解决 / 巡检 | 如何保证最终正确 | 兜住机制的不足 |
递进逻辑(读法:上层"逼出"下层):
CAP + FLP —— 约束可能性空间
↓ 迫使做出
CP / AP —— 行为选择
↓ 落地为
Quorum / Lease / 复制协议 —— 机制
↓ 仍不足,需要
幂等 / 冲突解决 / 巡检 —— 治理
认知价值:任一理论都不能孤立比较。CAP 是约束、CP/AP 是决策、Lease 是工具、治理是兜底——处于不同层,回答不同问题。后续章节即按此链逐层展开,读者可随时回到此图定位。
CAP 定理只适用于副本型分布式数据系统,并且:
CAP 讨论的是当网络分区发生时,系统被迫表现出的行为约束。
本质:多个副本对外表现为一个原子对象
CAP 的 C 只是"一致性"这一名词的最强特例:线性一致性位于一致性谱系顶端,其下还有顺序、因果、最终一致等更弱级别。完整谱系与强弱关系见 分布式数据.html
概念澄清:两种一致性
"Consistency"在不同语境下含义完全不同,混用是分布式设计的高频误区:
| 术语 | 出处 | 约束对象 | 含义 |
|---|---|---|---|
| Consistency(CAP-C) | CAP 定理 | 单个数据对象 | 线性一致:读总返回最近写,多副本对外如一个原子对象 |
| Consistency(ACID-C) | 数据库事务 | 应用业务不变式 | 事务前后满足完整性约束(是应用契约,非分布式机制) |
CAP-C 是机制层保证,ACID-C 是业务层契约,两者正交:前者约束分布式副本对外的读写表现,后者约束应用数据的完整性。ACID-C 与隔离性的机制拆解见 分布式事务.html。
CAP 中的可用性 ≠ 运维意义上的高可用(HA)
网络分区不是异常,而是必须接受的现实前提
在一个可能发生网络分区的副本系统中:
无法同时保证:
- 所有副本表现为一个线性一致的整体
- 所有请求在有限时间内必然返回结果
证明思路(Gilbert-Lynch,反证法):设两节点 G1、G2 因分区无法互通。客户端写 G1,A 迫使 G1 无需等待 G2 确认即返回成功;随后客户端读 G2,A 同样迫使 G2 必须立即响应,但它收不到那次更新,只能返回旧值,于是违反线性一致(C)。分区中 G2 只有"无限等待(违反 A)"与"返回旧值(违反 C)"两条路,别无第三选择——矛盾即证三者不可兼得。
因此,CAP 要求:在分区发生时,系统必须明确牺牲一致性还是可用性
CAP 限定"分区时能保证什么",FLP 定理则限定"异步网络中共识能否完成":
在完全异步的网络中,只要存在一个可能崩溃的节点,就不存在能保证终止的确定性共识算法。
P 不可放弃(分区是前提,非选项),故分区时的取舍只剩两种行为模式:CP(保一致,牺牲可用)与 AP(保可用,容忍不一致)。二者的差异不止于"分区期间是否拒绝请求",而贯穿分区期间、恢复期、常态的整个生命周期。
| 维度 | CP(保一致) | AP(保可用) |
|---|---|---|
| 分区期间·写 | 无法凑齐 Quorum 的一侧拒绝写(阻塞或报错) | 任一节点都接受写 |
| 分区期间·读 | 仅返回可保证最新的读,否则拒绝 | 始终返回,可能是陈旧值 |
| 失效粒度 | 少数派失能,多数派仍正常服务(非全局瘫痪) | 两侧均可服务,各自独立演化 |
| 分区恢复后 | 无需和解——从未接受过冲突写 | 必须冲突消解——合并两侧分叉的写 |
| 冲突解决 | 不涉及(机制层已阻止冲突) | LWW / CRDT / 应用层合并(详见下文 BASE 层) |
| 正确性归属 | 机制层(Quorum + 共识协议) | 治理层(冲突规则 + 幂等 + 巡检) |
| 常态延迟(PACELC-EL) | 高:写需同步复制多数派,≥ 一轮 RTT | 低:本地就近响应,异步复制 |
| 典型系统 | Spanner、etcd、ZooKeeper、单主 Postgres | Cassandra、Dynamo、Riak |
本质:CP 把正确性锁在机制层——用"拒绝少数派"换"永不冲突",代价是可用性与延迟;AP 把正确性推到治理层——用"先接受、后和解"换"永远在线",代价是复杂的冲突消解。取舍的实质,是决定正确性由机制保证还是由治理兜底。保证正确性的代价不会消失,只会转移。
CP 与 AP 只在分区发生时才形成冲突:网络正常时,系统同时表现为 CA——CAP 描述的是极端条件下的行为。而分区是罕见事件,系统运行的绝大多数时间处于无分区常态,此时 CAP 沉默。
但常态无 C/A 冲突,不等于常态无取舍——取舍只是换了一个维度:延迟 vs 一致性。这正是 PACELC 要补上的盲区。
if Partition(分区时):在 A 与 C 间取舍;else(常态):在 L(延迟)与 C 间取舍。
延迟取舍的根因:强一致要求写操作同步复制到多数副本才返回,读写延迟 ≥ 一轮消息往返;放松一致性即可就近响应、降低延迟。
CAP 是 PACELC 的特例:当消息延迟趋于无穷(分区),"延迟取舍"退化为"可用性取舍"。
| 分类 | 分区时 | 常态 | 典型系统 |
|---|---|---|---|
| PA/EL | 保可用 | 保低延迟 | Dynamo、Cassandra、Riak |
| PC/EC | 保一致 | 保一致 | Spanner、传统 ACID 库、HBase |
| PA/EC | 保可用 | 保一致 | MongoDB(默认) |
| PC/EL | 保一致 | 保低延迟 | 理论存在,工程罕见 |
认知价值:Dynamo 系"常态也牺牲一致性"并非因为分区,而是 EL 选择。仅用 CAP 无法解释这一点,延迟取舍才是日常架构的主约束。
CAP 与 PACELC 只揭示取舍的存在,选 CP 还是 AP 取决于业务需求(金融倾向 CP,购物车倾向 AP),理论本身不给答案。一旦业务权衡后选择了 AP,放弃强一致之后,一个允许不一致的系统如何保证最终仍然正确?
这正是 BASE 的职责:
AP 架构落地后的一致性治理哲学——用治理体系(冲突解决、幂等、巡检)让"暂时不一致"最终收敛回正确。
关键:最终一致 ≠ 自动正确
最终一致的"正确性"从何而来?
难点不在"何时一致",而在"一致到的值对不对"。"最终一致"只免费给你收敛(所有副本终将取同一个值),却不保证正确——规则选错,系统会一致地收敛到一个错误的值:对账户余额用 LWW(后写胜),会悄无声息丢掉一笔真实交易。而"收敛到什么才算对"依赖业务语义,无法通用自动化。
正确性依赖于:
BASE 是一种治理体系,而不是算法保证。
一致性的落地需要三类工具,对应"达成 → 检测 → 修复"三个环节:
| 环节 | 工具 | 解决的问题 |
|---|---|---|
| ① 达成一致 | Quorum(空间)、Lease(时间) | 多副本如何就一个值达成一致 |
| ② 检测冲突 | 版本向量 / 向量时钟、逻辑时钟、HLC | 判断两次写是因果先后还是并发冲突 |
| ③ 修复收敛 | 反熵(Merkle Tree)、读修复、提示移交、CRDT | 检测并弥合已产生的副本分歧 |
三类构成因果链:① 尽量不产生分歧 → ② 分歧产生后先能识别 → ③ 再将其收敛回正确。CP 侧重 ①(用 Quorum 阻止分歧),AP 侧重 ②③(先接受、后收敛)。
Quorum 管空间(多副本如何就一个值达成一致),Lease 管时间(一段时间内谁有权威)。前者是根本保证,后者是性能优化。
Quorum:核心不是"多数派",而是集合相交约束——
W + R > N 时,任意读集合与任意写集合必相交,读一定碰到最新写。
调 W、R 即在一致性与延迟/可用性间滑动,也是防脑裂的数学基础(多数派唯一,少数派自动失能)。All / One / Any 只是 W、R 取极值的特例。
Lease:对"一段时间内一致性"的时限承诺,依赖有界时钟漂移。它是 CP 的性能优化、AP 的冲突窗口收窄手段,不是一致性的根本保证。
冲突解决的前提是先能识别冲突,核心是给每次写附加"因果戳":
检测层只回答"是否冲突、谁先谁后",不负责如何合并——合并交给 ③。
对已产生的分歧,靠三种时机 + 一种数据结构收敛:
机制层③提供了收敛的技术手段,但工具不会自动生效、也覆盖不了自身失效的情况——治理层负责确保它们持续、正确地运行:
机制层保证"能收敛",治理层保证"确实收敛、且收敛到对的值"。没有治理体系的 BASE,只是"概率正确"。
这些理论不是并列知识点,而是一条逐步修正认知盲区的升级链:
| 年份 | 理论 | 修正了什么 |
|---|---|---|
| 2000 | CAP(Brewer 猜想) | 确立分区下 C/A 不可兼得 |
| 2002 | Gilbert-Lynch 证明 | 将 CAP 猜想升为定理 |
| 2008 | BASE(Dan Pritchett) | 为 AP 侧提供最终一致的治理范式 |
| 2010 | PACELC(Abadi) | 补上 CAP 遗漏的常态延迟维度 |
| 2012 | Spanner / TrueTime | 用有界时钟(commit-wait)逼近全球强一致,工程上打破"必弃强一致"的教条,外部一致性强于线性一致性 |
| 2014 | I-Confluence(Bailis) | 给出免协调的可判定判据:操作集合保持不变式合流,即可无需协调 |
| 2019 | CALM 定理(Hellerstein-Alvaro) | 免协调且一致 ⟺ 程序可用单调逻辑表达;把 CAP 从"不可能"转为"可判定" |
主线:从"分区时二选一"(CAP)→"常态延迟也要付费"(PACELC)→"用工程手段逼近强一致"(Spanner)→"判定何时根本无需协调"(CALM)。理论从描述取舍走向消除不必要的取舍——不可能性的边界,正被工程与理论从两侧同时收窄。
全文六层认知,从"约束"到"免除"层层递进:
分布式一致性问题
├── 理论约束层:CAP(分区取舍)+ FLP(共识可终止性)—— 划定不能做什么
├── 时间维度层:PACELC(常态延迟取舍)—— 补上常态也要付费
├── 工程策略层:CP / AP(行为选择)—— 在约束内决策
├── 机制实现层:① 达成(Quorum/Lease) → ② 检测(向量时钟) → ③ 修复(反熵/CRDT)
└── 治理修正层:监控 / 巡检 / 人工介入 —— 确保收敛且收敛到对的值
↑
免协调判据:CALM —— 单调的部分,本就无需协调
四句锚点:
CAP / FLP 划定不能做什么,PACELC 补上常态也要付费; CP / AP 是决策,Quorum / CRDT 是工具,治理是兜底; 正确性的代价从不消失,只在机制层与治理层之间转移; 而 CALM 指出:单调的那部分,本就无需付费。