文章目录
题目背景
某电商平台为提升系统性能,采用 MySQL 作为主数据库,同时引入 Redis 作为缓存存储热点数据。系统主要支持商品信息查询、库存管理及订单存储等业务:
| 业务 | 特点 |
|---|---|
| 商品详情 | 访问频繁,需快速响应 |
| 库存 | 需实时准确,支持高并发修改 |
| 订单 | 需长期保存,查询频率较低 |
数据分工:
- Redis:热门商品基本信息(名称、价格等)、实时库存数量、热销商品排名等。
- MySQL:完整商品数据、库存明细、订单全量信息及用户数据。
本题围绕热点数据在缓存失效时可能出现的 缓存击穿(热点 Key 失效瞬间大量请求直达数据库) ,分别考察 互斥锁方案(王工) 、逻辑过期方案(李工) 的流程填空与方案对比。
概念速记:缓存击穿
缓存击穿 :某个 Key 非常热点,在某一时刻被超高并发访问;当该 Key 失效的瞬间,持续的大并发"穿透"缓存直接请求数据库,导致数据库压力骤增甚至故障。
互斥锁思路 :缓存过期后,大量并发中只有 首个成功拿到锁 的线程去查库并回写缓存;其余线程 等待/重试,待缓存就绪后从缓存读取,从而避免同一热点多次打库。
逻辑过期思路 :在缓存值中附带 逻辑过期时间 ,物理上可不依赖 Redis TTL 立即删键;过期后 异步 从数据库刷新,期间仍可 先返回旧数据,以换取低延迟与高吞吐(容忍短暂不一致)。
题目 2.3.1【问题1】(6分)
针对热点数据可能发生的缓存失效问题,架构师 王工 提出基于 互斥锁 的缓存实现方案。请补充架构图(序列图「互斥锁」)中的空白 (1) ~ (6)。
图意说明(线程1 / 线程2)
- 线程1:缓存未命中后,作为成功拿到锁的线程,完成「查库 → 回写 → 释放锁」。
- 线程2 :缓存未命中后,在循环内 抢锁失败则休眠再重试 ,直到缓存被线程1写好,最终 缓存命中。
下列序列图按真题常见 左右两泳道(线程1 / 线程2) 绘制:左侧线程1 自顶向下完成「未命中 → 加锁 → 查库 → 回写 → 释锁」;右侧线程2 在 循环 内完成「未命中 → 抢锁失败 → 休眠重试」,退出循环后 缓存命中 。填空 (1)~(6) 与图中序号一致。为贴近试卷排版,不单独拉出 Redis/MySQL/锁对象泳道,访问缓存与数据库体现在步骤说明中。

读图说明: 时间线上线程1 与线程2 并发 进入;线程2 在循环中多次「失败 → 休眠 → 再查缓存」,直到线程1 写完缓存后某次查询 命中 跳出循环。若需在图中显式画出对 Redis/MySQL 的消息,可在备考时另画带
缓存/数据库参与者的展开图;答卷填空以本题五步 + 线程2 循环三步为准。
参考答案(填空)
| 序号 | 内容 |
|---|---|
| (1) | 获取互斥锁成功 |
| (2) | 查询数据库 |
| (3) | 更新缓存 |
| (4) | 释放锁 |
| (5) | 获取互斥锁失败 |
| (6) | 休眠一会,重试 |
解析
缓存击穿场景中,互斥锁是常用手段:只有首个线程 在缓存失效后访问数据库并更新缓存,其他线程 暂停等待 ;首线程释放锁后,其余线程 直接从缓存读取,避免对数据库的并发冲击。
题目 2.3.2【问题2】(8分)
针对同类问题,架构师 李工 提出 逻辑过期 方案。请补充架构图(含「逻辑过期时间」、多线程协作)中的空白 (1) ~ (8)。

参考答案(填空)
注:真题图中锁的表述可能写作「分布式锁」或「互斥锁」,语义一致:同一热点更新互斥即可。
| 序号 | 内容 |
|---|---|
| (1) | 获取分布式锁成功 |
| (2) | 开启新线程 |
| (3) | 返回旧数据 |
| (4) | 查询数据库 |
| (5) | 更新缓存 |
| (6) | 释放锁 |
| (7) | 获取分布式锁失败 |
| (8) | 返回旧数据 |
解析
逻辑过期通过在缓存数据中 额外存储逻辑过期时间 ;过期后 不立即删除缓存 ,而是 启动异步任务 从数据库加载最新数据并写回缓存;刷新期间 仍返回旧数据 ,避免请求阻塞。代价是可能出现 短时不一致。
图意说明(典型三线程版本)
- 线程1 :发现逻辑过期 → 加锁成功 → 启动新线程(异步刷新) → 立即返回旧数据(不阻塞用户)。
- 线程2(后台) :查库 → 更新缓存并重置逻辑过期时间 → 释放锁。
- 线程3 :发现逻辑过期 → 加锁失败 → 直接返回旧数据(与线程1抢锁失败时的处理一致,避免集体打库)。
完整流程还可包含 线程4 :逻辑时间已被线程2刷新后,缓存命中且未过期 ,返回新数据。图示常强调:不设置物理过期 / 逻辑过期 、高可用、性能好 ,但存在 短暂不一致 。

题目 2.3.3【问题3】(11分)
对比 王工(互斥锁方案) 与 李工(逻辑过期方案) 各自的优缺点。
参考答案(要点)
互斥锁方案
优点:
- 数据一致性高:同一时刻仅一个线程访问数据库并更新缓存,减少并发写缓存、读脏数据等问题,一致性较好。
- 实现简单直观:过期后抢锁 → 查库 → 回写 → 释放,流程清晰。
缺点:
- 线程阻塞 :持锁线程若查库/写缓存较慢,其他线程长时间等待,响应时间变差。
- 死锁风险 :异常路径若未释放锁,可能造成 死锁(需超时、finally、看门狗等治理)。
- 性能问题 :高并发下大量线程阻塞等待锁,吞吐下降。
逻辑过期方案
优点:
- 非阻塞 :逻辑过期后仍可 立即返回(多为旧数据),请求不被长时间阻塞。
- 性能好 :线程竞争与等待少,并发能力相对更强。
缺点:
- 数据不一致 :刷新完成前用户可能读到 过期数据 ,难以保证强一致,多为 最终一致。
- 实现复杂 :需维护逻辑过期字段、异步刷新、锁与缓存更新的 原子性/协作,边界情况多。
- 内存占用 :数据不随物理 TTL 立即淘汰时,可能 长期占内存,需额外淘汰或容量策略。
解析(综合)
互斥锁与逻辑过期都是应对 缓存击穿 的常见策略。
-
互斥锁 :缓存失效(未命中)时,首个请求线程尝试获取互斥锁;成功则查库、更新缓存并释放锁,失败则 等待 直至锁释放。通过 串行化数据库访问 保证一致性,但高并发下大量线程等待会 增加延迟、降低吞吐 ,更适合 一致性要求极高、并发相对可控 的场景。
-
逻辑过期 :缓存"过期"后仍可先 返回旧数据 ,同时 异步 查库更新;不阻塞主流程,并发能力与体验 更好,但存在 短暂不一致 ,更适合 高并发、可容忍短时不一致 的业务(如电商展示、资讯类读多写少场景)。
考点小结
- 缓存击穿 与 缓存雪崩 、缓存穿透 的区别(本题侧重热点 Key 失效瞬间)。
- 互斥锁 :强一致、实现简单,代价是 阻塞与锁治理。
- 逻辑过期 :高可用、低延迟,代价是 一致性减弱与工程复杂度。