一句话

分布式系统里,C / A / P 三者最多只能满足两个。又因为网络分区一定会发生(P 不可避免),所以现实中你只能在 CPAP 之间二选一。

CAP 三个字母

字母含义通俗理解
Consistency一致性任何时候读到的数据都是最新写入的
Availability可用性每次请求都能在合理时间内返回响应(不超时、不报错)
Partition tolerance分区容错性节点之间网络断开/丢包时,系统仍能继续工作

为什么必选 P

只要是「分布式」系统,节点之间靠网络通讯,就一定会遇到丢包、延迟、机房断网。P 不是一个选项,是事实。所以真正在选的,是 CP 还是 AP

  • CP:网络分区时,宁可拒绝服务也要保证强一致 → ZooKeeper、etcd、HBase
  • AP:网络分区时,宁可返回旧数据也要保证可用 → Cassandra、Eureka、DNS

一个具体例子

主从两节点 MySQL,主从间网络断了:

  • CP 派:从库直接拒绝读请求(避免读到旧数据)→ 一致但不可用
  • AP 派:从库继续返回旧数据 → 可用但不一致

注意:CAP 里的「一致性」是 强一致性(线性一致性 / 顺序一致性),不是日常语境的”数据正确”。

BASE:AP 的工程化补丁

CAP 是理论极端,工程上多数业务并不需要”每次读到的都是当下最新”。BASE 是 eBay 工程师对 AP 的工程化总结:

字母含义实际做法
Basically Available基本可用部分功能/性能降级,核心可用(限流、熔断、降级)
Soft state软状态允许中间状态存在(订单”处理中”、消息”投递中”)
Eventually consistent最终一致一段时间后数据收敛到一致(异步同步、补偿、对账)

最终一致的常见手段

  • 消息队列:写主库 → 发 MQ → 其它服务异步消费更新
  • 定时对账:每日 T+1 跑账,发现不一致就补
  • TCC / Saga:拆成 Try-Confirm-Cancel 或可补偿的子事务
  • 读修复 / 反熵:Cassandra 风格的后台一致性修复

CAP vs ACID vs BASE

视角单机数据库分布式(强一致派)分布式(最终一致派)
模型ACIDCP(CAP 中选 CP)AP + BASE
例子MySQL 单实例ZooKeeper、etcdCassandra、DynamoDB
取舍不用考虑分区牺牲可用性牺牲强一致

选型速查

业务推荐原因
配置中心、服务注册表CP(etcd、ZK)配错比看不到更可怕
服务发现(高可用优先)AP(Eureka、Nacos AP)拿到旧节点列表也比拿不到强
商品详情页、信息流AP + 缓存读多写少,最终一致足够
支付、库存扣减CP 或强一致中间件钱出错没法解释
消息系统看场景Kafka 偏 AP;RabbitMQ 镜像队列偏 CP

常见误区

  1. “NoSQL 都是 AP” —— 错。MongoDB 主从用 majority 写就是 CP;Cassandra 也能调到接近 CP。
  2. “我有事务就有 C” —— 单机 ACID 的 C 跟 CAP 的 C 不是一回事,前者是数据库约束,后者是多副本可见性。
  3. “BASE 是 NoSQL 专属” —— BASE 本质是工程取舍思路,传统业务一样用:MQ + 对账就是典型 BASE。

参考