1. 缓存一致性概述

1.1 缓存一致性问题定义

缓存一致性(Cache Consistency)是指在分布式系统中,缓存层与持久化存储层(如数据库)之间数据副本的同步程度。当应用程序同时使用缓存和数据库时,同一份数据可能在不同存储介质中存在多个副本,这些副本之间的值差异即为缓存不一致。

核心定义:缓存一致性 = 缓存中的数据与数据库中的数据在任意时刻保持逻辑等价的程度。完全一致意味着缓存命中返回的值与数据库查询返回的值完全相同;不一致则意味着两者存在偏差。

从一致性强度维度,缓存一致性可分为三个级别:

一致性级别 描述 典型场景
强一致性 缓存更新后,所有后续读取立即看到最新值 金融交易、库存扣减
最终一致性 允许短暂不一致,但保证经过足够时间后数据一致 用户资料、内容推荐
弱一致性 不保证后续读取能看到更新,甚至可能永远看不到 日志聚合、非关键统计
缓存一致性定义:数据副本偏差模型 应用服务 Redis 缓存 MySQL 数据库 写入/同步 不一致区域 缓存副本 ≠ 数据库副本 偏差时间窗口:Δt = t₂ - t₁ t₁: 数据库更新完成 t₂: 缓存失效/更新完成

1.2 为什么需要缓存一致性

引入缓存的核心目的是降低延迟和减轻数据库负载,但缓存与数据库之间的数据偏差会引发一系列业务问题。以下从三个维度说明缓存一致性的必要性:

  • 业务正确性受损:用户读取到过期数据,导致展示错误、计费偏差、库存超卖等直接经济损失。
  • 用户体验下降:同一用户在不同页面或不同时间看到矛盾的数据(如订单状态反复变化),降低信任度。
  • 系统可靠性风险:不一致数据可能触发下游系统的错误逻辑,造成级联故障或数据污染。
经验法则:缓存一致性不是"要不要"的问题,而是"在什么粒度、什么延迟容忍度下达成一致"的问题。业务对一致性的要求直接决定了缓存策略的选择。

不同业务场景对缓存一致性的容忍度差异巨大:

业务场景 一致性要求 可容忍偏差时间 推荐策略
商品库存 强一致 < 100ms 缓存同步更新 + 分布式锁
用户头像 最终一致 1~5 分钟 缓存过期 + 异步刷新
热门文章阅读数 弱一致 10~30 分钟 定时批量回写
支付状态 强一致 < 50ms 缓存穿透 + 实时校验

1.3 缓存与数据库不一致的典型场景

在实际生产环境中,缓存不一致主要由并发写入、操作时序错乱和异常中断三类原因引发。以下是六种最常见的典型场景:

  1. 先更新数据库,后更新缓存(写写冲突):线程A更新数据库为v1,线程B更新数据库为v2,但B先更新缓存为v2,A后更新缓存为v1,导致缓存最终为旧值v1。
  2. 先删除缓存,后更新数据库(读写冲突):线程A删除缓存后,线程B读取缓存未命中,从数据库加载旧值写入缓存,然后线程A才更新数据库,导致缓存长期为旧值。
  3. 先更新数据库,后删除缓存(删除失败):数据库更新成功,但删除缓存时网络超时或Redis异常,缓存中残留旧数据。
  4. 缓存过期与数据库更新交错:缓存刚好过期,请求A从数据库加载旧数据,同时请求B更新数据库为新数据,A将旧数据写回缓存覆盖新值。
  5. 主从复制延迟:写入主库后缓存已更新,但从库尚未同步,后续读请求从从库获取旧数据并更新缓存。
  6. 分布式事务失败:缓存更新成功但数据库回滚,或数据库提交成功但缓存更新超时,两端状态不一致。
典型不一致场景:先删缓存 + 读写交错 时间 线程A(写):删除缓存 线程A(写):更新数据库 → v2 线程B(读):缓存未命中 线程B(读):从DB加载旧值v1 线程B(读):将v1写回缓存 最终状态:缓存 = v1(旧值),数据库 = v2(新值) 缓存与数据库永久不一致
关键警示:上述"先删缓存 + 读写交错"场景是生产环境中最常见、最难排查的不一致问题。它不需要并发写入,仅需一个读请求在删除缓存之后、数据库更新之前插入,就能造成永久性不一致。这也是为什么业界更推荐"延迟双删"或"先更新数据库后删除缓存"策略的原因。