1. 缓存一致性概述

1.1 缓存一致性问题产生的根源

缓存一致性问题本质上是多副本数据在不同时间点出现值差异的现象。当系统引入缓存层后,同一份数据在数据库(主副本)和缓存(从副本)中同时存在,写操作无法原子性地同步更新所有副本,便产生了不一致窗口。

核心矛盾:数据库与缓存是两个独立的存储系统,不支持跨系统分布式事务。任何写操作都面临“先写库还是先写缓存”的选择,而网络延迟、并发冲突、节点故障都会放大不一致窗口。

产生不一致的典型场景包括:

  • 并发写冲突:两个线程同时更新同一数据,一个写库成功但缓存更新被另一个覆盖。
  • 操作顺序颠倒:先删缓存后写库,在写库完成前另一个请求读取到旧数据并回填缓存。
  • 部分失败:写库成功但缓存更新超时或节点宕机,缓存永久保留旧值。
  • 主从延迟:读写分离架构下,缓存基于从库构建,从库同步延迟导致缓存落后于主库。
场景 不一致窗口 影响范围 典型修复手段
并发写冲突 毫秒级 单条记录 分布式锁、版本号校验
操作顺序颠倒 取决于写库耗时 单条记录 延迟双删、异步队列补偿
部分失败 直到缓存过期或修复 单条记录 重试机制、binlog订阅
主从延迟 秒级到分钟级 批量记录 强制读主、缓存TTL缩短

1.2 CAP理论在缓存场景下的体现

CAP理论指出分布式系统在一致性(Consistency)、可用性(Availability)、分区容错性(Partition Tolerance)三者中最多同时满足两个。缓存系统作为分布式数据层的核心组件,其一致性策略直接受CAP约束。

关键认知:在分布式缓存场景中,网络分区是必然发生的(P必须选),因此实际选择在C和A之间权衡——即CP架构或AP架构。

缓存场景下的CAP取舍:

  • CP架构(放弃A):当缓存节点发生网络分区时,牺牲可用性保证一致性。例如:Redis Cluster在分片不可达时返回错误,拒绝读取可能不一致的数据。适用于金融交易、库存扣减等场景。
  • AP架构(放弃C):网络分区时继续提供服务,允许短暂不一致。例如:本地缓存+Redis组合,分区时读取本地旧数据。适用于商品详情页、用户Feed流等场景。
  • CA架构(放弃P):单机缓存或同机房部署,不涉及网络分区。例如:单机Redis、Memcached。但生产环境几乎无法避免分区,CA仅存在于理论。
CAP理论在缓存场景下的三角取舍 C 一致性 A 可用性 P 分区容错性 CP 架构 放弃可用性,保证一致性 AP 架构 放弃一致性,保证可用性 CA 架构 放弃分区容错(单机/同机房) 生产环境网络分区不可避免,P必须选,实际在C和A之间权衡 CP:Redis Cluster分区拒绝 | AP:本地缓存+Redis降级 | CA:单机Redis

1.3 最终一致性与强一致性选择

在缓存一致性设计中,强一致性和最终一致性是两种核心模型,选择取决于业务对数据准确性和系统可用性的容忍度。

强一致性(Linearizability)

写操作完成后,任何后续读操作都能立即读到最新值。实现方式包括:

  • 同步双写:写数据库成功后同步写缓存,使用分布式锁或事务保证原子性。
  • 读写串行化:所有读写请求通过一致性哈希路由到同一节点,避免并发冲突。
  • 缓存穿透读主库:每次读缓存前校验版本号,不一致时强制从主库读取并回填。
代价:强一致性会显著降低系统吞吐量(通常下降30%-50%),增加写延迟,且在节点故障时可能短暂不可用。适用于支付、库存、订单状态等场景。

最终一致性(Eventual Consistency)

写操作完成后,系统保证在没有新写入的情况下,经过一段“不一致窗口”后所有副本最终达到一致。实现方式包括:

  • 缓存过期+异步回填:设置TTL,过期后由读请求触发回填,容忍短暂不一致。
  • 异步队列补偿:写库后发送MQ消息,消费者异步更新缓存,允许秒级延迟。
  • binlog订阅:监听数据库变更日志(如Canal),异步同步到缓存,延迟通常在毫秒到秒级。
适用场景:最终一致性适用于对实时性要求不高的读多写少场景,如用户资料、商品详情、配置信息。不一致窗口通常控制在1秒以内,用户体验几乎无感知。
对比维度 强一致性 最终一致性
不一致窗口 0(无窗口) 毫秒~秒级(可配置)
读延迟 高(可能穿透到主库) 低(直接命中缓存)
写吞吐 低(同步锁/事务开销) 高(异步写入)
可用性 分区时可能降级 分区时仍可服务
实现复杂度 高(分布式锁/版本控制) 中(MQ/过期策略)
典型业务 支付、库存、订单 用户资料、商品详情、Feed流
强一致性 vs 最终一致性:缓存写入流程对比 强一致性流程 客户端写请求 获取分布式锁 同步写数据库 同步写缓存 最终一致性流程 客户端写请求 写数据库成功 发送MQ消息 异步更新缓存 强一致性:写完成即可读 | 最终一致性:MQ消费完成后才一致

1.4 选择决策矩阵

在实际架构设计中,选择强一致性还是最终一致性需要综合评估以下因素:

  • 业务容忍度:数据不一致是否导致资损、用户体验下降或合规风险。
  • 读写比例:读多写少场景更适合最终一致性,写密集场景需评估锁竞争。
  • 缓存命中率:高命中率下不一致窗口影响面小,低命中率需考虑穿透压力。
  • 运维成本:强一致性需要分布式锁、版本控制等基础设施,最终一致性依赖MQ和监控。