Skip to content

CAP 定理

CAP 定理又称布鲁尔定理(Brewer's Theorem),是分布式系统领域最重要的理论之一,由 Eric Brewer 于 2000 年提出。它揭示了分布式系统设计中一个无法回避的取舍困境。


一、前置概念:什么是网络分区?

网络分区(Network Partition) 是指分布式系统中,因网络故障(交换机宕机、光纤中断、路由异常等)导致部分节点之间的通信被切断,系统被迫分裂成若干个相互隔离的子网络。

正常状态:          发生网络分区:

Node A ─── Node B   Node A     Node B
  │           │       │           │
Node C ─── Node D   Node C  ✂  Node D

所有节点互通       A/C 与 B/D 之间通信中断

关键理解

分区内的节点依然可以互相通信,但跨分区的节点无法交换数据。网络分区在真实的分布式环境中随时可能发生,因此分区容错性(P)是几乎无法放弃的前提。


二、CAP 的三个特性

C — 一致性(Consistency)

任意时刻,所有节点看到的数据完全相同。客户端无论读哪个节点,都能得到最新的写入结果。

🌰 生活类比:银行柜台和 ATM 机显示的余额必须完全一致,不能出现柜台显示 1000 元、ATM 显示 800 元的情况。

A — 可用性(Availability)

每个非故障节点都必须在合理时间内响应请求,系统不能因为部分节点异常就拒绝服务。

🌰 生活类比:即使银行某个后台系统在维护,ATM 机也应该还能正常取款,而不是直接显示"服务不可用"。

P — 分区容错性(Partition Tolerance)

即使网络发生分区,系统仍然能继续对外提供服务,不会因为节点间通信中断而整体崩溃。

🌰 生活类比:上海和北京的数据中心之间的专线断了,但两地的用户依然能正常使用系统。


三、CAP 定理的结论

核心结论

一致性(C)、可用性(A)、分区容错性(P),三者最多只能同时满足其中两个。

在真实的分布式系统中,网络分区是客观存在的,P 几乎是必须保证的。因此实际上的选择往往是:

  • CP:保证一致性,牺牲部分可用性
  • AP:保证可用性,牺牲强一致性(转为最终一致性)
        C(一致性)
        /        \
      CP          CA
      /              \
P(分区容错)——AP—— A(可用性)

CA:传统单机数据库(不存在分区问题)
CP:ZooKeeper、etcd、HBase
AP:Cassandra(默认)、CouchDB、DNS

四、应用场景与决策

场景背景

假设有一个分布式数据库集群,由于网络故障,集群被分成 分区 A分区 B,两个分区内部可以正常通信,但分区之间的通信中断。

此时系统必须在 C 和 A 之间二选一(P 已无法避免)。


选择 CP:保一致性,牺牲可用性

做法:分区 B 检测到无法与主节点通信后,拒绝所有写请求,只允许主分区 A 继续提供读写服务。分区恢复后再同步数据。

效果:数据绝对不会出现冲突,但分区 B 的用户在故障期间无法写入数据。

适用系统

  • 银行转账、支付系统(余额不能出现两份不同的值)
  • 库存扣减(不能超卖)
  • 分布式锁、配置中心

代表中间件ZooKeeperetcdHBase


选择 AP:保可用性,牺牲强一致性

做法:分区 A 和分区 B 各自继续提供读写服务,互不干扰。网络恢复后再通过数据同步机制(如"最后写入者胜出"、"向量时钟"、"合并策略")解决冲突,达到最终一致性

效果:用户在任何时候都能访问和操作,但在故障期间可能读到稍旧的数据。

适用系统

  • 社交媒体点赞数、评论(短暂不一致可以接受)
  • 购物车(用户看到的商品数量短暂有偏差无关紧要)
  • DNS 解析(全球节点不强求实时同步)

代表中间件Cassandra(默认配置)、CouchDBDynamoDB

最终一致性

AP 模式并不是"放弃一致性",而是将强一致性降级为最终一致性——允许数据在短时间内不同步,但保证在网络恢复后最终达到一致的状态。


五、主从复制中的 CP 与 AP

CP 模式(常见于关系型数据库)

网络分区发生时,只有主节点所在分区继续提供写服务,从节点分区拒绝写入,等待主节点恢复连接后再同步。

分区前:  主(A) ──同步──> 从(B)
分区后:  主(A) 继续写入   从(B) 拒绝写入,等待恢复

AP 模式(常见于 NoSQL 数据库)

网络分区发生时,主从节点各自继续接受读写,分区恢复后通过冲突解决策略进行数据合并。

分区前:  主(A) ──同步──> 从(B)
分区后:  主(A) 继续写入   从(B) 也继续写入(可能产生冲突)
恢复后:  主(A) + 从(B) 进行数据合并,达到最终一致

注意

Cassandra、MongoDB 等数据库并非固定属于某种模式,它们支持通过一致性级别配置在 CP 和 AP 之间灵活调整。例如 Cassandra 设置 ALL 级别时偏向 CP,设置 ONE 级别时偏向 AP。


六、如何选择?

考量维度选 CP选 AP
数据错误的代价极高(如资金、库存)可接受(如点赞数、浏览量)
用户对不可用的容忍度较高(等一下没关系)极低(必须随时可用)
业务对数据实时性要求严格(必须读到最新)宽松(稍旧也可以接受)
典型业务金融、医疗、电商支付社交、内容、推荐系统