CAP 定理是什么?BASE 理论和最终一致性怎么理解?

进阶高频原理约 6 分钟读完

一句话回答

CAP 说的是:分布式系统发生网络分区(P)时,一致性(C)和可用性(A)只能保一个。分区在真实网络里一定会发生,所以 P 不是可选项,真正的选择是"分区时选 C 还是选 A":选 C 就拒绝一部分请求,选 A 就可能返回旧数据。etcd、ZooKeeper 这类协调服务是 CP;Cassandra、Eureka 这类偏 AP。BASE(基本可用、软状态、最终一致)是选择 A 之后的工程思路:允许短暂不一致,但保证没有新写入后,各副本最终会收敛到同一个值。

详细解析

C、A、P 的准确含义

字母 含义 容易误解成
C(Consistency) 线性一致性:所有读都能读到最近一次完成的写,整个系统看起来像只有一份数据 数据库 ACID 里的 C(满足约束),两者不是一回事
A(Availability) 每个没有故障的节点收到请求后,都必须在有限时间内给出非错误的响应 "99.99% 的可用率",CAP 里的 A 是一个更极端的定义
P(Partition tolerance) 节点之间的消息可能丢失或无限延迟,系统仍要继续工作 "可以选择不容忍分区"

CAP 由 Eric Brewer 在 2000 年提出,2002 年 Gilbert 和 Lynch 给出了形式化证明。

为什么不是"三选二"

文本
        分区发生
   节点 1  ──X──  节点 2
   x = 2           x = 1(还没同步)

客户端向节点 2 读 x:
  选 C:节点 2 拒绝请求或等待(牺牲 A)
  选 A:节点 2 返回 x = 1(牺牲 C)

网络分区不是你能"不选"的东西,交换机故障、GC 停顿、跨机房链路抖动都会造成分区。所以 CA 系统在分布式场景下基本不存在,单机数据库才谈得上 CA。

另外两点:

  • 没有分区时 C 和 A 可以兼得。CAP 只约束分区期间的行为,不是说系统平时就要放弃什么
  • 选择可以细到操作级别。同一个系统里,下单走强一致,商品浏览量走最终一致,很常见

常见系统怎么选

类型 例子 分区时的行为
CP etcd、ZooKeeper、Consul 基于多数派共识,少数派一侧的节点不能提供写服务
AP Cassandra、Eureka、DNS 各分区继续读写,恢复后再合并或修复数据
可调 Cassandra 的读写一致性级别、MongoDB 的 readConcern/writeConcern 按请求选择强弱

CP 系统靠 Raft 这类共识算法实现。Redis 主从是异步复制,主节点确认过的写可能还没同步到从节点,切换后就丢了,所以它不提供 CP 的保证,常被归为偏 AP(严格说它也不满足 CAP 定义里的 A),这也是 Redis 分布式锁 在主从切换时会丢锁的原因。

BASE 和最终一致性

BASE 是对 ACID 的反向取舍:

  • 基本可用(Basically Available):出故障时允许损失部分功能或性能,比如降级、响应变慢,但核心功能可用
  • 软状态(Soft state):允许存在中间状态,比如"支付中",副本之间允许暂时不一致
  • 最终一致(Eventually consistent):没有新的更新后,经过一段时间,所有副本会达到一致

业务里最常见的落地是:本地事务 + 消息异步通知其他服务,配合重试和对账,见 分布式事务方案。

一致性模型从强到弱

模型 保证
线性一致性 读到最新写入,所有操作有一个全局顺序且符合真实时间
顺序一致性 所有节点看到相同的操作顺序,但不要求符合真实时间
因果一致性 有因果关系的操作(先看到帖子才回复)顺序一致,无关的操作可以乱序
读己之写、单调读 面向会话:自己写的自己能读到;读过新值后不会再读到旧值
最终一致性 只保证最终收敛,中间读到什么都有可能

PACELC 是对 CAP 的补充:有分区(P)时在 A 和 C 之间取舍;没分区(Else)时在延迟(L)和一致性(C)之间取舍。同步复制到多数派更一致但更慢,这才是系统平时真正面对的权衡。

面试官可能追问

ZooKeeper 是 CP,那它的读一定是最新的吗?

不一定。ZooKeeper 的写经过 Leader 和多数派确认,是线性一致的;但读请求由客户端连接的那个节点直接返回,这个节点可能还没同步到最新数据。官方文档的保证是顺序一致性,并不承诺不同客户端在同一时刻看到相同的数据。需要读较新的值时,可以先调用 sync 让这个节点追上 Leader 再读。etcd 默认的读是线性一致读(要经过 Raft 确认),也可以指定 serializable 读,换取更低延迟,代价是可能读到旧值。

注册中心应该选 CP 还是 AP?

多数人倾向 AP。注册中心的数据短暂不一致,最多是调用到一个刚下线的实例,客户端重试就行;但如果因为分区拒绝服务,所有服务都拿不到地址列表,影响面大得多。Eureka 就是这个思路。用 ZooKeeper 做注册中心的系统,客户端通常会缓存服务列表来弥补。

最终一致的"最终"是多久?

没有理论上限,取决于复制延迟、重试间隔和故障恢复时间。工程上要做两件事:监控复制延迟或消息积压,让"最终"可观测;用定时对账发现长时间没有收敛的数据,再人工或自动修复。

易错点

  • 把 CAP 理解成"三个里随便选两个",实际是分区发生时在 C 和 A 之间选
  • CAP 的 C 是线性一致性,和 ACID 的 C 不是一个概念
  • CAP 的 A 要求每个非故障节点都能响应,不等于平时说的"高可用"
  • 说某个系统是 CP 或 AP 往往过于简化,很多系统的一致性级别可以按操作配置

AI 模拟面试官

用自己的话回答,AI 对照参考答案打分、指出遗漏,再追问,最多 3 轮

登录后就可以和 AI 面试官对练,面试记录也会保存下来。登录

这道题你掌握了吗?

选一个最接近的状态,没掌握的题会出现在"我的进度 · 待复习"里。

学习记录暂存在本机浏览器。登录后自动同步到账号,换设备也能看到。