{T}

一致性:CAP 与一致性模型

0. 引言

单机数据库中,一致性由事务的 ACID 保证。引入网络与多副本后,同一份数据的不同副本可能返回不同结果——分布式一致性要解决的问题,就是在网络分区、节点失效的前提下,让系统对外表现出可预期的数据状态。本文从 CAP 定理出发,展开一致性谱系与选型权衡。

1. 为什么需要分布式一致性

  • 单机:ACID 事务保证"读到的总是正确状态";
  • 分布式:写入发生在主节点,副本异步/同步传播——副本间必然存在可见性差异
  • 目标:在分区与故障下,定义并保证"读操作返回什么状态是合理的"。

2. CAP 定理与常见误解

CAP 指出分布式系统在三个属性中最多同时满足两个

属性含义
一致性(C)每次读取都能拿到最新写入(线性一致)
可用性(A)每个非故障节点都能在有限时间内响应请求
分区容错性(P)网络分区发生时,系统仍能继续工作

由于网络分区是必然事件,P 是必选项,实践中的权衡是 CP(保一致弃可用) 还是 AP(保可用弃强一致)

常见误解

  1. "三选二"是静态的——实际是分区发生时决定牺牲哪一项,分区恢复后二者都可恢复;
  2. CAP 中的 C 是线性一致,不等于事务隔离级别中的"一致性",也不同于最终一致性;
  3. 可用性指"每个请求都有响应",而非响应内容正确。

3. 一致性的实现基础

一致性依赖两件事:

text
复制(Replication):在多副本间传播数据(详见《数据分布:分片与复制》)
共识(Consensus):在多个副本间就写入顺序达成一致(详见《分布式协调》章)
  • 只有复制无共识 → 副本各自为政,收敛靠运气;
  • 复制 + 共识 → 全局顺序确定,可支持强一致读。

4. 一致性谱系(从强到弱)

图表渲染中…
级别定义代价典型
线性一致任意读都能看到最新写入,所有操作有全局一致的时间顺序(= CAP 的 C)需全局排序,延迟高,地理分布难实现ZooKeeper、etcd
顺序一致所有节点看到同一顺序,但不要求与真实时间一致Raft 日志应用顺序
因果一致有因果关系的操作保序,并发操作可乱序中低社交评论、IM
会话一致同一会话内读己之写(Read-Your-Writes),跨会话不保证购物车、登录态
单调读同一客户端多次读,不会读到比之前更旧的值缓存、Feed
最终一致无新写入经过足够时间,所有副本最终收敛最低AP 系统(Cassandra/DynamoDB)
text
最强 → 最弱:线性一致 > 顺序一致 > 因果一致 > 会话/单调读 > 最终一致

5. 选型权衡

级别延迟可用性适用
线性一致元数据、分布式锁、选主
因果一致社交、协作编辑
会话一致用户会话类业务
最终一致缓存、浏览计数、Feed

决策原则:先问业务"读旧值会造成什么后果"——锁/选主/账务必须线性一致;内容/计数最终一致即可;不要为"显得严谨"给全系统上强一致(详见《不同数据一致性模型有哪些应用?》)。

6. 与复制的关系

一致性级别由复制同步策略共识协议共同决定:

text
异步复制(无共识)   → 最终一致
半同步/Quorum        → 近似强一致(多数派内)
同步复制 + 共识协议  → 线性一致(TiDB Raft、etcd)

分布式数据库的典型实现:Raft 多数派复制 + 线性化读(TiDB/PolarDB-X/OceanBase),在"不丢已提交数据"与"分区可用性"之间给出工程最优解。

7. 小结

  • CAP:分区是必然,实际权衡是 CP vs AP;C 指线性一致;
  • 一致性谱系:线性 > 顺序 > 因果 > 会话/单调读 > 最终,强度与延迟/可用性成反比;
  • 实现基础:复制(传播数据)+ 共识(确定顺序)
  • 选型:按"读旧值的业务后果"决定级别,避免全系统一刀切。

下一章讲解存储引擎与查询:LSM-Tree 与 B+ Tree 的存储原理。