旁路缓存(Cache-Aside,CA)

业内最主流的缓存方案(90%互联网项目在用) ,又叫懒加载缓存 ,核心:数据库是权威数据源,应用程序全权管控缓存,缓存游离在数据库读写主链路之外(旁路),Redis/Memcached只做辅助加速,不会自动读写DB。

一、标准读写流程

1. 读流程(先查缓存,缺了查库回填)

  1. 应用先查缓存:命中→直接返回缓存数据
  2. 未命中(缓存无数据)→查询数据库→把DB结果写入缓存→返回数据

只有被访问过的数据才进缓存,不浪费内存

2. 写流程(先改库、后删缓存,不更新缓存)

  1. 第一步:优先更新数据库(DB落新数据)
  2. 第二步:删除对应缓存key(让旧缓存失效)

不做「更新缓存」,只删缓存,下次读自动从DB拉新数据回填

java 复制代码
// 伪代码
// 查询
public Object get(String key){
    Object val = cache.get(key);
    if(val == null){
        val = db.query(key);
        cache.set(key,val);
    }
    return val;
}
// 更新
public void update(String key,Object newVal){
    db.update(key,newVal); // 先改库
    cache.del(key);        // 再删缓存
}

二、为什么写操作「删缓存,不更新缓存」?

并发场景下更新缓存极易出现时序错乱、缓存存旧数据

  • A改DB=10,B改DB=20;B抢先更新缓存=20,A后更新缓存=10 → DB=20、缓存=10(脏数据)
  • 删除缓存:就算删失败,顶多下次读穿透DB,重新加载最新值,一致性更稳

三、优缺点

✅ 优点

  1. 实现简单、低侵入:缓存和DB解耦,缓存宕机业务降级查DB即可,不会整体雪崩
  2. 内存利用率高:按需加载,只缓存热点访问数据,冷数据不入缓存
  3. 通用性强:适配Redis、本地缓存等任意中间件,读多写少场景首选(商品、用户、资讯)

❌ 缺点

  1. 短暂数据不一致:DB更新成功→删缓存前,新读请求命中旧缓存(极短窗口期)
  2. 缓存穿透:不存在的数据频繁查询,每次都穿透到DB(用布隆过滤器/缓存空值解决)
  3. 缓存雪崩:大量key同时过期,批量请求打满DB(过期时间加随机偏移)

四、一致性优化:延迟双删(解决短时脏读)

  1. 更新DB → 立刻删缓存
  2. 延时50~500ms再次删缓存

干掉删缓存间隙中,并发读写入的旧缓存,大幅降低不一致概率

五、对比另外两种缓存模式(面试常考)

模式 管控方 写逻辑 适用场景
旁路CA 应用 改库+删缓存 读多写少(绝大多数业务)
读写穿透 缓存中间件 读写都先走缓存,缓存自动同步DB 写频繁、要求强一致
写回WriteBehind 缓存异步 只更缓存,异步批量刷DB 超高吞吐、可容忍丢少量数据

六、适用场景

商品详情、用户基础信息、配置数据、首页资讯等读远大于写业务,是Java后端面试高频考点。

相关推荐
鲨鱼辣钊1 分钟前
【FastAPI筑基-Day19】APScheduler定时任务全实战|自动执行、动态启停、后台常驻
java·spring·fastapi
不正经学生2 小时前
C语言预处理详解:编译器真正动手之前的那些事
c语言·开发语言·算法·面试·bug
门思科技2 小时前
LoRaWAN 设备类别:Class A、B、C 对比与选型指南
c语言·开发语言·php
恋恋西风4 小时前
C++ 理解 std::thread 在单核和多核上的行为差异
开发语言·c++
学长毕业设计4 小时前
基于SpringBoot的公益基金管理系统(源码+文档+讲解视频)
java·spring boot·后端
Brilliantwxx4 小时前
【Linux】 进程(9)程序与进程地址空间(基础+进阶+面试题)
linux·运维·服务器·开发语言·c++
东小西5 小时前
【SAA实战】第 3 篇 · 工具调用全攻略:把业务能力交给 Agent 自己调度
java·后端·spring
东小西5 小时前
【SAA实战】第 4 篇 · Agent 短期记忆:saver 让 Agent 跨轮记得住(threadId 隔离)
java·后端·spring
许彰午5 小时前
22-DataCenter报文序列化
java·低代码·架构·状态模式
2601_962065255 小时前
[MySQL] SQL优化之性能分析
java·sql·mysql