Yihui’s Blog

什么是缓存击穿?如何解决?

日期:2026-09-27
标签:#面试 #场景设计 #Redis
难度:中等
来源:牛面场景题
答案说明:独立整理(站内题目标记为 VIP,未读取会员答案)

一句话答案

缓存击穿是一个存在的热点键失效后,大量并发读同一时间回源;核心是让同一键的重建合并、限制回源并发,并按业务陈旧容忍度决定是否返回旧值。

面试口语版(约 60 秒)

比如爆款商品详情刚过期,很多请求同时看到缓存未命中,都去查数据库,单个热点键就能造成回源尖峰。常用办法是在应用内或跨实例做“同键只让一个请求重建”:抢到重建资格的请求查数据库并回填,其他请求短暂等待、重试缓存,或在允许陈旧时返回旧值。重建者还要在获得资格后再查一次缓存,防止重复加载。若数据库不可用,不能让等待者无限堵住,要设置等待超时、并发上限和降级策略。对可预测的热点可提前刷新。要注意互斥重建降低的是重复查询,不能解决单个查询本身慢,也不能让旧值适用于库存等强一致判断。

请求流程

flowchart TD
    A[读取热点键] --> B{缓存命中?}
    B -- 是 --> C[返回]
    B -- 否 --> D{获得重建资格?}
    D -- 是 --> E[再次查缓存]
    E --> F{仍未命中?}
    F -- 是 --> G[查询权威数据并回填]
    F -- 否 --> C
    G --> C
    D -- 否 --> H{允许返回旧值?}
    H -- 是 --> S[返回旧值]
    H -- 否 --> I[等待并重试缓存]
    I --> T{等待超时?}
    T -- 否 --> A
    T -- 是 --> J[降级或限流]

若重建资格使用 Redis 锁,应有短租约、唯一令牌和条件释放;重建者崩溃时资格最终要释放。若多个实例只使用各自进程内的 single-flight,每个实例仍可能各自回源,需按下游容量判断是否足够。

取舍与易错点

  • 互斥重建:减少数据库并发,但等待者延迟上升;重建慢时仍须超时和降级。
  • 逻辑过期 / 旧值兜底:响应平稳,但会返回陈旧数据,只适合可容忍陈旧的页面或推荐结果。
  • 预热与提前刷新:适合已知热点,需处理刷新失败和实际热点变化。
  • 关注每键未命中量、同键回源并发、重建耗时、等待超时和旧值返回比例。

面试官递进追问

  1. 击穿和穿透在“数据是否存在”上有什么区别?
  2. 为什么获得重建锁后还要再次检查缓存?
  3. 重建者崩溃或数据库超时,等待请求如何避免堆积?

自测

  • 不看笔记,60 秒解释热点键过期到数据库尖峰的链路。
  • 给“商品详情”和“实时库存”分别选一种兜底方式,并解释陈旧值边界。

参考资料

资料核对日期:2026-09-27。

Maintained by · YihuiEdit on GitHub

Keep reading

View all posts

如何为Redis分布式锁设置合理的超时时间?

日期:2026-09-27 标签:#面试 #场景设计 #Redis 难度:中等 来源:牛面场景题 答案说明:独立整理(站内题目标记为 VIP,未读取会员答案) 一句话答案 租约应覆盖可预期的执行、暂停与网络抖动,同时限制故障后的等待;没有可靠耗时上界时用有身份校验的受控续期,并在业务资源侧防止旧执行者写入。 面试…

Read article

怎么用Redis实现可重入的分布式锁?

日期:2026-09-27 标签:#面试 #场景设计 #Redis 难度:中等 来源:牛面场景题 答案说明:独立整理(站内题目标记为 VIP,未读取会员答案) 一句话答案 为同一把锁保存“本次最外层获锁的唯一令牌 + 重入次数 + 租约”;嵌套调用共享该令牌并原子递增,释放时递减,次数归零才删除。新一轮独立获锁必…

Read article

基于 Redis 实现分布式锁有什么优缺点?

日期:2026-09-27 标签:#面试 #场景设计 #Redis 难度:简单 来源:牛面场景题 答案说明:独立整理(站内题目标记为 VIP,未读取会员答案) 一句话答案 Redis 锁接入简单、响应快,适合容忍少量故障窗口内重复执行的任务;租约过期与主从切换可能破坏互斥,关键写入还须在资源侧拒绝旧持有者。 面试…

Read article