第二章:缓存经典问题与一致性保证

在本章中,我们聚焦分布式缓存面试最高频的三大核心场景:缓存穿透/击穿/雪崩、过期淘汰策略、缓存与数据库一致性。每个问题背后不仅是技术方案,更考察你对异常流量、数据一致性和系统容错的工程理解。

缓存经典问题 穿透/击穿/雪崩 过期与淘汰策略 缓存与数据库一致性 布隆过滤器 互斥锁/限流 定期+惰性删除 LRU/LFU/随机 延迟双删 消息队列同步 回答路径:定义现象 → 分析根因 → 给出方案 → 对比优缺点

3个核心面试问答

📌 面试问题

请解释缓存穿透、缓存击穿、缓存雪崩的区别,并给出解决方案。

🎯 面试官考察点
  • 是否理解三种异常现象的本质区别
  • 能否给出工程可落地的多级防护方案
  • 对基础组件的熟悉程度(布隆过滤器、互斥锁等)
📐 回答框架
  1. 区分定义:穿透(查不存在key)、击穿(热点key过期)、雪崩(大面积key同时过期)
  2. 根因分析:短时间大量请求打到底层
  3. 分别给出方案:布隆过滤器/空值缓存(穿透);互斥锁/永不过期+异步更新(击穿);过期时间加随机值/集群限流(雪崩)
💬 简短示例回答

缓存穿透是对不存在key的请求穿透到DB,可用布隆过滤器拦截;缓存击穿是热点key过期瞬时高并发DB,用互斥锁或永不过期+异步更新;缓存雪崩是大量key同时过期,解决方案包括过期时间加随机值、本地缓存+限流降级。核心是避免DB被冲垮。

❓ 可能追问
  • 布隆过滤器如何删除元素?
  • 互斥锁方案下如果获取锁失败怎么办?
  • 你用过哪些分布式限流组件?
⚠️ 避坑提醒

不要把“穿透”和“击穿”混淆;不要只提理论不提实现细节(如布隆过滤器大小/误判率);避免说“所有key都加随机过期时间”,要根据业务区分热点与非热点。

📌 面试问题

Redis的过期策略和内存淘汰机制分别是什么?如何选择淘汰策略?

🎯 面试官考察点
  • 是否理解定期删除+惰性删除的组合原理
  • 能否结合业务场景说明淘汰策略选择
  • 对内存模型和性能影响的认知
📐 回答框架
  1. 过期策略:定期随机抽样删除(默认每100ms抽20个) + 惰性删除(访问时检查)
  2. 淘汰机制:8种策略,重点讲 LRU、LFU、TTL、allkeys-lru
  3. 选型依据:根据访问频率、数据时效性、业务容忍度(如缓存穿透风险)
💬 简短示例回答

Redis过期采用定期删除+惰性删除两者结合,避免单次全量遍历阻塞。内存淘汰我用最多的是allkeys-lru,适合缓存场景;对于热点和时间敏感业务,可用volatile-ttl。关键是设置合理最大内存,防止OOM。

❓ 可能追问
  • LRU和LFU在Redis中如何近似实现?
  • 如果淘汰策略选了noeviction,会有什么后果?
  • 如何监控Redis的内存淘汰情况?
⚠️ 避坑提醒

不要只说“LRU”,要提Redis的近似LRU(随机抽取key比较idle time);不要混淆过期策略和淘汰机制;避免建议用volatile-lru但不设置过期时间导致内存泄漏。

📌 面试问题

如何保证缓存与数据库的一致?延迟双删的流程是怎样的?

🎯 面试官考察点
  • 是否理解缓存一致性中的读写竞争场景
  • 能否给出延迟双删的实现细节(延迟时间设定)
  • 是否了解更优方案(如订阅binlog+消息队列)
📐 回答框架
  1. 问题点:并发写入时,缓存与DB更新顺序不一致导致脏数据
  2. 延迟双删:先删缓存→写DB→sleep(100ms)→再删缓存
  3. 优缺点:简单,但延迟时间需根据业务读写耗时调优;可配合消息队列最终一致
💬 简短示例回答

延迟双删流程:先删除缓存,再更新数据库,休眠一段时间(通常500ms,根据读请求耗时设定),再次删除缓存。目的是避免在更新数据库期间,读请求将旧数据写入缓存。生产中我还会结合MQ重试二次删除,保证最终一致。

❓ 可能追问
  • 为什么是“先删缓存”而不是“先写DB”?
  • 延迟时间如何确定?
  • 如果第二次删除失败,如何补偿?
⚠️ 避坑提醒

避免认为延迟双删可以完全杜绝不一致(极端情况仍有脏数据窗口);不要忽略第二次删除可能失败,需增加重试/监听binlog;不要将“先删后写”与“先写后删”混淆;强调“最终一致性”而非“强一致性”。

📖 面试官视角提示: 大厂在考察缓存问题时,往往希望听到可度量的参数(如布隆过滤器误判率1%、延迟双删睡眠500ms)、多级防御(本地缓存+分布式缓存+限流)、监控报警(缓存命中率、内存使用率、淘汰次数)。回答时最好带上你实际调优过的数字。