Skip to content

从单机到分布式:CAP 与 BASE

本文是分布式系统系统学习系列的 L1 入门篇。前置:无。 学完可以配合面试题食用:01-cap-theory-ca-ap

为什么分布式:单机扛不住的三件事

假设你写了一个电商网站,一开始一台 4C8G 的服务器撑了 1000 个用户。用户涨到 10 万,数据库连接池满了,CPU 长期 90%,半夜宕机就全站不可用。这是单机容量瓶颈,纵向扩容(换更强的机器)总有天花板且成本线性增长。

更糟的是:一台机器挂了,所有用户都连不上——单点故障。如果你把服务部署到两台机器,一台挂了另一台还能接流量,这叫高可用。如果两台机器放在不同城市,某地停电或光缆被挖断,另一地还能服务,这叫异地容灾

这三个推力——容量、单点、容灾——把「一台机器跑到底」的模式推向了分布式。

网络是不可靠的:分区是常态,不是事故

分布式系统里的「网络」和单机内存总线不一样:数据包可能丢、延迟可能几百毫秒、对方可能挂了、也可能只是慢。发送一个请求后,你得到三种可能结果,而不是两种:

  • 成功:收到正常响应
  • 失败:明确返回错误
  • 超时:什么都不知道

超时是最坑的——你不知道是请求没到,还是到了但响应没回来,还是对方处理完但回复丢了。这就是分布式系统的三态结果:成功、失败、未知。

分区(network partition)指的是两个节点之间网络断开,但各自还在运行。这不是事故,这是分布式系统要面对的正常状态。一个系统如果从设计上就没考虑分区,到了生产环境遇到网络抖动就会崩。

CAP 直觉版:分区时只能二选一

CAP 三个字母代表:

  • C(Consistency):所有节点看到同一份数据,读到的都是最新写入
  • A(Availability):每次请求都能收到一个(非错误)响应
  • P(Partition tolerance):即使网络分区发生,系统也继续运行

很多人记住的是「CAP 三选二」,但这句话有误导性。P(分区容忍)不是可选项——只要部署了多节点,分区就一定会发生。所以真正的问题是:当分区发生时,你在 C 和 A 之间选哪个?

正常情况 ──► 两个节点互相通信 ──► C 和 A 可以同时满足
分区发生 ──► 两个节点断开了 ──► 必须在 C 和 A 之间做选择

来做个思考实验。两个节点 A 和 B,各自维护一个计数器 counter。用户写入 A 成功,B 收到这个写请求吗?

mermaid
sequenceDiagram
    participant User
    participant Node_A
    participant Node_B
    User->>Node_A: SET counter = 1
    Node_A->>Node_B: 同步数据
    Note over Node_A,Node_B: 网络断开!
    Node_B->>User: GET counter → 0(旧值)
    User->>Node_A: GET counter → 1(新值)

CP 选择:分区时停止服务或拒绝写,等恢复后再提供。保证一致性,但牺牲可用性。ZooKeeper、etcd 在这类系统里。

AP 选择:分区时两边都继续服务,数据可能不一致,等恢复后再合并。保证每次请求都有响应,但读到的可能是旧数据。Eureka、Cassandra 走这条路。

CA 不存在:不分区时 C 和 A 可以同时做到,但网络分区总会出现,所以「CA without P」在分布式条件下不存在。

CP/AP 的真实系统对照

场景选型代表性系统理由
配置中心 / 选主CPZK, etcd, Consul一致性错了会选错主,宁停不误
服务发现APEureka, Nacos AP注册信息略有延迟没关系,服务不可用不行
分布式存储CPTiDB, Spanner数据一致性不能妥协
缓存 / 内容分发APCDN, DNS旧数据也比没数据好
消息队列混合Kafka, Pulsar分区情况下选可用性,主副本选一致性

BASE:最终一致是工程妥协,不是理论

BASE 是「Basically Available, Soft state, Eventually consistent」的缩写,和 ACID 对着干:

  • Basically Available:系统出故障时仍然返回响应,可能返回降级结果
  • Soft state:系统状态随时间变化,不需要实时一致
  • Eventually consistent:数据最终会一致,但「最终」的时间量级不确定

最终一致不是一个理论定义,而是工程上的妥协——你允许系统在分区后的一段时间内不一致,但承诺「最终」会一致。这个「最终」多久,取决于:

  • 数据同步频率:秒级复制 vs 定时批量同步
  • 冲突检测机制:最后写入覆盖(LWW)还是向量时钟合并
  • 业务容忍度:用户昵称延迟 1 秒 vs 订单库存延迟 1 秒,承受力完全不同

动手实操

场景题:CP vs AP 选型

你设计一个分布式锁服务,用 ZK(CP)还是 Redis(AP)?为什么?

提示:锁的核心语义是「互斥」——若两个客户端同时拿到锁,数据就坏了。所以锁服务必须强制一致性,宁可锁不可用(等分区恢复),也不能让两个客户端同时拿到锁。ZK 的临时顺序节点 + watch 机制正是为此设计的。Redis 的 Redlock 在分区下可能同时解锁给两个客户端,所以不适合对互斥要求严格的场景。

常见误区与小结

  • 「CAP 三选二」:错。P 不是可选项,分区总会发生,只能在 C 和 A 之间选一个
  • 「CP 就是一致性,AP 就是可用性」:错。CP 在分区时牺牲可用性,正常时 C 和 A 都能满足
  • 「BASE 就是反 ACID」:BASE 是工程实践,不是理论约束。大部分实际系统在 ACID 和 BASE 之间取一个连续谱
  • 「最终一致就是最终会一致」:最终一致需要明确的时间承诺和冲突解决策略,光靠「最终」两个字不够

小结:CAP 是分布式系统的底层约束框架,BASE 是面对这个约束的工程应对。理解 CAP 的核心不是记住三个字母,而是理解「分区时怎么选」。下一篇进入一致性模型,从线性一致性到向量时钟,把「一致」这个词定义的精确。

参考

参考:Brewer's CAP Theorem(原始论文)、《Designing Data-Intensive Applications》第 7-9 章

手撕 → 框架 → 生产化,一步步把 AI Agent 工程化搞透。
粤ICP备2026104257号-1