Skip to content

CAP、BASE 与一致性问题

分布式里最容易被提到、也最容易被讲碎的几个词通常是:

  1. CAP
  2. BASE
  3. 一致性

很多人会背结论,但讲不清:它们到底在描述什么矛盾。

这篇文章重点讲:

  1. 一致性在分布式里到底指什么
  2. CAP 理论在说什么
  3. BASE 为什么会出现
  4. 企业系统里常见的一致性问题长什么样
  5. 为什么很多问题最后不是“选理论”,而是做权衡

1. 分布式里说的一致性,到底在说什么

在单机单库里,一致性问题往往相对简单。

但在分布式里,一致性通常要回答的是:多个节点、多个副本、多个服务看到的数据状态,什么时候应该一样,什么时候允许暂时不一样。

也就是说,这里的“一致性”不是只指数据库 ACID 里的那个词,而是:分布在不同节点上的状态能否按预期保持一致。


2. 为什么分布式里一致性会突然变难

因为一旦数据分散到多个节点,就会引入:

  1. 网络延迟
  2. 网络分区
  3. 节点故障
  4. 副本同步延迟

这几个问题在单机里几乎不存在,或者影响很小。

但在分布式里,它们会直接导致:

  1. A 节点已经更新了
  2. B 节点还没同步到
  3. 用户在不同节点读到的结果不一样

所以一致性问题,本质上不是“数据库设计差”,而是:分布式天然要面对网络和节点故障带来的状态分裂问题。


3. CAP 到底在说什么

CAP 是分布式系统里最经典的理论之一。

它讨论的是三个目标:

  1. Consistency
  2. Availability
  3. Partition Tolerance

3.1 Consistency

这里可以看成 同一时刻,所有节点看到的是一致的数据结果

3.2 Availability

可以理解成 每个请求都能得到响应,不让系统轻易直接拒绝服务

3.3 Partition Tolerance

可以理解成 即使节点之间网络出现分区,系统仍然要继续面对这种现实


4. CAP 真正的意思,不是“三选二”口诀这么简单

更具体一点,CAP 想表达的是:当网络分区真的发生时,系统通常无法同时完美满足一致性和可用性。

也就是说,真正的前提是:P 已经发生。

这时系统往往要在下面两种取向之间做权衡:

  1. 更偏一致性,宁可部分请求失败或等待
  2. 更偏可用性,先给响应,允许短暂不一致

所以很多人说的“三选二”,更好的理解方式其实是:分布式系统里网络分区几乎无法回避,因此关键是分区发生时你更优先保什么。


5. 一个最直观的例子

假设一个订单状态同时存在两个副本节点:

  1. 节点 A
  2. 节点 B

这时 A 和 B 之间网络断了。

如果用户请求到 A,把订单状态改成 PAID

5.1 偏一致性的做法

A 可能拒绝确认写入,或者阻塞等待 B 同步成功。

这样做的好处是:尽量保证所有节点最终看到一致结果。

代价是:请求可能失败、超时或不可用。

5.2 偏可用性的做法

A 先接受写入并返回成功,等网络恢复后再同步给 B。

这样做的好处是:系统继续可用。

代价是:短时间内不同节点读到的数据可能不一致。


6. BASE 为什么会出现

很多高并发互联网系统不会一味追求强一致,而会接受一种更现实的思路:在业务可接受范围内,允许状态暂时不一致,换取更高可用性和更高吞吐。

这就是 BASE 背后的语境。

BASE 通常包括:

  1. Basically Available
  2. Soft State
  3. Eventually Consistent

6.1 Basically Available

可以理解成 系统整体上尽量保持可用,但可能是降级后的可用

6.2 Soft State

可以理解成 系统状态允许在一段时间内不是绝对稳定的

6.3 Eventually Consistent

可以理解成 经过一段时间同步后,状态最终会趋于一致


7. 最终一致性到底是什么意思

最终一致性不是“永远不一致”,也不是“乱一会儿无所谓”。

更具体一点,它强调的是:系统允许在一个短暂窗口里出现状态差异,但最终要收敛到一致结果。

企业里很多常见场景都会接受这种模型,例如:

  1. 缓存与数据库短时间不一致
  2. 订单创建成功后积分稍后到账
  3. 搜索索引和主数据稍后同步

8. 分布式里常见的一致性问题有哪些

8.1 副本延迟

主节点已经写成功,从节点还没同步完成。

8.2 缓存双写不一致

数据库更新了,缓存还没删掉或没更新成功。

8.3 跨服务状态不一致

订单服务成功了,库存服务却失败了。

8.4 消息和本地事务不一致

本地事务提交了,但消息没成功投出去,或者反过来。

这些问题本质上都指向同一个核心:状态分散之后,更新不再天然原子。


9. 强一致是不是一定更好

不一定。

强一致的好处当然很直接:

  1. 语义更清晰
  2. 正确性更强
  3. 上层业务推理更简单

但代价也很明显:

  1. 延迟更高
  2. 吞吐可能更低
  3. 故障时可用性更差

所以工程上真正要问的不是:我要不要强一致。

而是:这个业务场景到底需要多强的一致性。


10. 企业里怎么做一致性权衡

通常会从下面几个维度去判断:

  1. 这个数据错一瞬间能不能接受
  2. 错了会不会产生资金、库存、订单类严重后果
  3. 读请求和写请求哪个更重要
  4. 对延迟和吞吐的容忍度如何

例如:

  1. 账户余额:通常更偏强一致
  2. 推荐列表:通常更能接受最终一致
  3. 搜索索引:通常更能接受短暂延迟同步

11. 工程上最容易混的几个边界

11.1 误区一:CAP 是设计数据库时才需要考虑的东西

不是。

只要系统涉及多节点、多副本、多服务状态同步,CAP 的权衡就已经在发生。

11.2 误区二:最终一致性就是不一致

不是。

它强调的是最终收敛,而不是放弃正确性。

11.3 误区三:所有系统都应该追求强一致

真实系统里,很多场景根本承受不起这个代价。


12. 一句话总结

CAP 在描述分布式里一致性和可用性的核心矛盾,BASE 在描述高可用系统里的现实取舍;而企业开发里真正重要的,不是背理论名字,而是判断一个业务场景到底需要多强的一致性,以及能接受多大的延迟和治理成本。

基于 VitePress 构建的个人技术笔记。