> For the complete documentation index, see [llms.txt](https://yeasy.gitbook.io/blockchain_guide/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yeasy.gitbook.io/blockchain_guide/04_distributed_system/cap.md).

# CAP 原理

CAP 原理最早出现在 2000 年，由加州大学伯克利分校的 Eric Brewer 教授在 ACM 组织的 Principles of Distributed Computing（PODC）研讨会上提出的猜想。两年后，麻省理工学院的 Nancy Lynch 等学者进行了理论证明。

该原理被认为是分布式系统领域的重要原理之一，深刻影响了分布式计算与系统设计的发展。

## 定义

**CAP 原理**：分布式系统无法同时确保一致性（Consistency）、可用性（Availability）和分区容忍性（Partition tolerance），设计中往往需要在网络分区发生时弱化对一致性或可用性的需求。

一致性、可用性和分区容忍性的具体含义如下：

* 一致性（Consistency）：指 CAP 语境下的原子一致性或线性一致性，系统对外表现得像只有一个最新副本，每个操作都在某个瞬间原子生效。它不同于 ACID 中约束事务把数据库从一个合法状态带到另一个合法状态的 Consistency；
* 可用性（Availability）：系统中每个非故障节点收到请求后，都能在有限时间内给出非错误应答；
* 分区容忍性（Partition tolerance）：节点之间的消息可能被网络任意丢失、延迟或隔离为多个分区时，系统仍能按协议继续运行。典型分区包括跨机房链路中断、交换机或防火墙配置错误、单向网络故障、长时间丢包或延迟。

CAP 原理认为，分布式系统最多只能保证三项特性中的两项特性。更准确地说，在必须容忍分区的分布式系统中，一旦分区实际发生，就必须在一致性和可用性之间取舍。

比较直观地理解，当网络可能出现分区时候，系统是无法同时保证一致性和可用性的。要么，节点收到请求后因为没有得到其它节点的确认而不应答（牺牲可用性），要么节点只能应答非一致的结果（牺牲一致性）。

在没有分区时，系统可以同时提供一致且可用的服务；当分区发生时，系统要么拒绝或延迟部分请求以保持一致性，要么继续响应但允许副本暂时分歧。

*注意：网络分区是可能存在的，出现分区情况后很可能会导致发生“脑裂”现象。*

## 应用场景

既然 CAP 三种特性不可同时得到保障，则设计系统时需要明确：网络分区发生时优先保持一致性还是可用性，或者限定系统不处理跨网络分区故障。

### 弱化一致性

对结果一致性不敏感的应用，可以允许在新版本上线后过一段时间才最终更新成功，期间不保证线性一致性。

例如网站静态页面内容、实时性较弱的查询类数据库、缓存、DNS，以及采用 Gossip 或 Dynamo 风格复制的存储系统，通常会优先保持可用性，并在分区恢复后通过冲突解决或后台同步收敛。

### 弱化可用性

对结果一致性很敏感的应用，例如账户余额、锁服务、元数据管理等，在系统无法确认最新状态时会拒绝或延迟部分请求。

Paxos、Raft、ZooKeeper、etcd 等基于多数派的协议主要处理这种情况。多数派分区可以继续推进；少数派分区为了避免产生两个不同结果，必须停止写入或返回不可用。

### 弱化分区容忍性

现实中，网络分区出现概率较小，但很难完全避免。对真正跨网络复制的分布式系统来说，分区通常不是可以被“弱化”的系统属性，而是必须被纳入故障模型的环境条件。

只有在不把跨节点网络分区纳入目标故障模型时，才可以说弱化分区容忍性。例如单机数据库、只依赖同一进程内共享内存的组件，或假设可靠 LAN 并在通信异常时整体阻塞、人工恢复的系统。

实践中，网络可以通过双通道、多可用区链路、超时检测和故障隔离等机制降低分区概率和影响，但无法从理论上消除分区。
