1. 缓存一致性基础:定义、产生原因与 CAP 体现

1.1 缓存一致性问题定义

缓存一致性(Cache Coherence)是指在多核处理器系统或分布式缓存系统中,当多个副本持有同一份数据的缓存时,所有副本在任何时刻对外呈现的值必须一致。一旦某个副本被修改,其他副本必须及时同步,否则将出现脏读或过期数据。

核心定义: 对于任意内存位置 X,在任何时间点,所有缓存副本对 X 的读取操作必须返回最近一次写入操作的值(或该写入操作的后续一致状态)。

1.2 产生原因分析

缓存一致性问题主要源于两个场景:多核共享内存与分布式节点复制。下表对比了两者的根本差异:

场景 根本原因 典型架构 一致性粒度
多核 CPU 每个核心拥有私有 L1/L2 缓存,写操作先到达本地缓存,其他核心不可见 SMP / NUMA 缓存行(Cache Line)
分布式缓存 数据在多个节点间复制,网络延迟导致更新传播滞后 Redis Cluster / Memcached 键值对(Key-Value)

1.3 多核场景下的写传播与串行化

多核缓存一致性需要解决两个子问题:

  • 写传播(Write Propagation): 一个核心的写操作必须被其他核心感知。
  • 写串行化(Write Serialization): 所有核心必须看到相同的写操作顺序。

下图展示了四核系统中,核心 0 修改变量 X 后,其他核心缓存行失效的典型流程:

多核缓存一致性 — 写失效传播流程 核心 0 L1 缓存 (X=1) 核心 1 L1 缓存 (X=0) 核心 2 L1 缓存 (X=0) 核心 3 L1 缓存 (X=0) 共享总线 / 目录协议(MESI 嗅探) 写 X=1 失效 失效 失效 说明:核心 0 写入 X=1 后,总线广播失效消息, 核心 1/2/3 的 L1 缓存行被标记为 Invalid,下次读取必须从主存重新加载。

1.4 分布式缓存中的一致性问题

在分布式系统中,缓存一致性面临更复杂的挑战:

  • 网络分区: 节点间通信可能中断,导致更新无法传播。
  • 副本延迟: 主从复制存在时间窗口,从节点可能返回旧数据。
  • 并发写入: 多个客户端同时修改同一缓存键,产生冲突。
典型陷阱: 许多团队在分布式缓存中只关注“最终一致性”,却忽略了业务对“读己之写”的强一致性要求。例如用户修改个人信息后立即刷新页面,若缓存未同步,将看到旧数据,造成体验断裂。

1.5 CAP 理论在缓存中的体现

CAP 理论指出,分布式系统在一致性(Consistency)、可用性(Availability)和分区容错性(Partition Tolerance)三者中最多同时满足两个。缓存系统作为分布式数据层,必须做出明确取舍:

CAP 组合 缓存策略示例 典型场景 代价
CP (一致 + 分区) ZooKeeper 缓存、强一致缓存锁 分布式锁、配置中心 分区时不可用,牺牲可用性
AP (可用 + 分区) Redis 异步主从、CDN 缓存 商品详情页、新闻 feed 可能返回过期数据,牺牲一致性
CA (一致 + 可用) 单机缓存、本地内存缓存 单体应用、嵌入式系统 无法容忍网络分区,分布式下不现实

下图展示了 CAP 三角在缓存设计中的决策路径:

CAP 理论在缓存中的决策三角 C 一致性 A 可用性 P 分区容错 CP: ZooKeeper / 强一致锁 AP: Redis 异步复制 CA: 单机缓存(无分区) 缓存设计核心权衡 选 CP 还是 AP? 业务容忍度决定 读多写少 → AP

1.6 一致性模型分类

根据 CAP 取舍,缓存一致性模型可细分为以下层次:

  1. 强一致性(Linearizability): 写操作完成后,任何后续读操作立即返回新值。实现代价高,通常需要分布式共识协议(如 Paxos/Raft)。
  2. 最终一致性(Eventual Consistency): 如果没有新写入,所有副本最终会收敛到相同值。DNS 缓存、CDN 是典型例子。
  3. 因果一致性(Causal Consistency): 有因果关系的操作必须按顺序被所有节点看到,无因果关系的操作可以并发。
  4. 读己之写(Read-Your-Writes): 客户端写入后,同一客户端后续读取一定能看到自己的写入。
实践建议: 在微服务缓存设计中,优先识别业务对一致性的真实需求。例如“库存扣减”必须强一致,而“用户头像”可以接受最终一致。不要为所有数据统一选择最高一致性级别,否则会无谓牺牲性能和可用性。

1.7 本章小结