Redis的旁路缓存策略和先删除缓存后更新数据库,先更新数据库后删除缓存,这三种策略之间有什么关系??

文章目录

      • [1. 旁路缓存策略 (Cache Aside Pattern) ------ 总体架构](#1. 旁路缓存策略 (Cache Aside Pattern) —— 总体架构)
      • [2. 三者的逻辑演进与竞争态分析](#2. 三者的逻辑演进与竞争态分析)
        • [A. 先删除缓存,后更新数据库](#A. 先删除缓存,后更新数据库)
        • [B. 先更新数据库,后删除缓存(Cache Aside 标准做法)](#B. 先更新数据库,后删除缓存(Cache Aside 标准做法))
      • [3. 三种策略的关系总结表](#3. 三种策略的关系总结表)
      • [💡 深度思考:为什么是"删除"而不是"更新"缓存?](#💡 深度思考:为什么是“删除”而不是“更新”缓存?)

这是一个非常经典且高频的后端面试/实战问题。简单来说,它们之间的关系是: "旁路缓存(Cache Aside)"是一个宏观的架构模式,而另外两者是实现该模式中"更新操作"的具体时序方案。

作为后端开发者,你可以把它们看作是"抽象接口"与"具体实现"的关系。


1. 旁路缓存策略 (Cache Aside Pattern) ------ 总体架构

这是目前互联网最通用的缓存模式。它的核心逻辑分为两部分:

  • 读请求: 先读缓存,缓存命中则返回;缓存失效则读数据库,然后将数据写回缓存。
  • 写请求(关键点): 先更新数据库,然后让缓存失效(删除缓存)。

它们的联系就在这里: 当我们要执行"写请求"时,究竟是"先删缓存后更新数据库"还是"先更新数据库后删除缓存",这就是你提到的另外两种具体策略。


2. 三者的逻辑演进与竞争态分析

为了保证数据库(Source of Truth)和缓存的一致性,我们需要分析在并发环境下,这两种时序会发生什么。

A. 先删除缓存,后更新数据库

这种方案在并发环境下非常脆弱,容易产生永久性脏数据

  1. 线程 A 执行写操作,先删除了缓存
  2. 此时线程 B 执行读操作,发现缓存缺失,去读数据库(旧值)
  3. 线程 B 将旧值写入缓存
  4. 线程 A 更新数据库(新值)
  • 结果: 缓存里永远是旧值,数据库里是新值。除非缓存过期,否则不一致会一直持续。
  • 修复方案: 采用"延时双删"策略(在更新完 DB 后,sleep 一段时间再删一次缓存)。
B. 先更新数据库,后删除缓存(Cache Aside 标准做法)

这是业界最推荐的方案,虽然理论上仍有极其微小的概率出现不一致,但概率极低。

  1. 线程 A 执行读操作,缓存刚好失效,读数据库(旧值)
  2. 线程 B 执行写操作,更新数据库(新值) ,然后删除缓存
  3. 线程 A 将此前读到的旧值写入缓存
  • 结果: 产生脏数据。
  • 为什么概率低? 因为步骤 3(写缓存)的速度远快于步骤 2(更新 DB),通常读线程会在写线程删除缓存前就完成写入。
  • 修复方案: 配合消息队列(MQ)进行重试删除,确保缓存最终一定被删掉。

3. 三种策略的关系总结表

维度 旁路缓存 (Cache Aside) 先删缓存,后更库 先更库,后删缓存
层级关系 架构模式(顶层设计) 写操作的具体实现方案 A 写操作的具体实现方案 B
核心目的 保证 DB 与 Cache 最终一致 试图通过先清理缓存来强制触发加载 默认方案,降低并发冲突概率
并发风险 取决于写操作的时序 极高(容易产生永久脏数据) 极低(仅在读快于写时发生)
典型补救 无(需结合具体方案) 延时双删 MQ 异步重试删除

💡 深度思考:为什么是"删除"而不是"更新"缓存?

在 Cache Aside 模式中,无论是 A 还是 B 策略,大家通常都选择删除缓存 (Delete),而不是更新缓存(Update)。原因有二:

  1. 性能开销: 如果缓存的数据是经过复杂计算得到的(比如多次 Join),每更一次库就更新一次缓存,代价太大。采用"懒加载"更合适。
  2. 并发安全: 如果两个写线程并发更新缓存,可能出现 DB 是新值,但缓存被旧的写请求覆盖的情况(类似丢失更新)。

总结建议:

在你的 Java 后端开发实践中(比如你之前提到的《小哈书》微服务项目),直接采用 "先更新数据库,后删除缓存" 即可。如果对一致性要求极高,可以引入 Canal 监听 MySQL binlog 来异步删除 Redis 缓存,这样可以解耦业务代码并解决删除失败的问题。

你目前的项目里,是否有遇到因为高并发导致的缓存不一致现象?如果有,我们可以针对具体的业务场景(比如点赞数、评论列表)聊聊更细化的处理手段。

相关推荐
哈__1 小时前
从 MySQL 到在线表格:NocoDB 自托管部署、数据导入与远程访问
数据库·mysql
倔强的石头1062 小时前
高可用与无感扩容——分布式时序数据库选型指南
数据库·分布式·时序数据库
袋鼠云数栈10 小时前
实时湖仓如何真正做到“数据够新”?
大数据·数据库·人工智能·数据治理
ACP广源盛1392462567310 小时前
M6/M5 Pro Mac mini 端侧 AI 落地@ACP#YLB3116 中端多盘存储扩展在 AI 服务中的机会与应用场景
大数据·网络·数据库·人工智能·嵌入式硬件·macos
ACP广源盛1392462567311 小时前
M6/M5 Pro Mac mini 端侧 AI 新形态@ACP#GSV5800 Serdes 长距离视频传输在 AI 服务中的机会与落地场景
大数据·网络·数据库·人工智能·嵌入式硬件·macos·音视频
倔强的石头_13 小时前
事务边界与批量写入:避免长事务、锁等待和日志压力
数据库
努力努力再努力wz13 小时前
【Redis入门系列】从 KEYS 到 SCAN:渐进式遍历、Cursor 与位反转原理
数据库·redis·缓存
坐吃山猪13 小时前
【多线程】Lock与Condition
大数据·数据库
互联网叫兽14 小时前
redis深入学习一
redis
小宋102114 小时前
大模型成本怎么控制:Token统计、缓存与模型路由实战
人工智能·缓存