--- tags: [test/review, redis, cache-penetration, cache-breakdown, cache-avalanche, bloom-filter] create time: 2026-08-09 12:00 --- # 缓存穿透击穿雪崩解决方案_测试题 ## 概述 本测试覆盖 Redis 缓存三大经典问题——穿透(Penetration)、击穿(Breakdown)和雪崩(Avalanche)。共 10 道题:6 道选择题、3 道填空题、1 道简答题,考察对各自成因的区分理解和对应方案的设计能力。 --- ## 一、选择题(6道,由浅入深) > **难度阶梯**: Q1-Q2 基础概念 → Q3-Q4 核心原理 → Q5-Q6 深入应用/边界场景 ### Q1(基础)— 考察定义层面 以下哪种现象描述的是"缓存穿透"? A. 热点 key 过期时大量并发请求同时查到缓存为空,纷纷去查 DB B. 大量 key 在同一时刻过期导致请求洪水面涌向下流 C. 恶意用户反复查询数据库中不存在的 key,每次缓存都 miss 直接打到 DB D. 单个 key 的访问频率远高于平均水平,超过 Redis 实例处理能力 ### Q2(基础)— 考察行为判断 布隆过滤器(Bloom Filter)在查询某个 key 时返回"可能存在",这表示: A. 该 key 一定存在于数据集中 B. 该 key 一定不存在于数据集中 C. 该 key 可能存在也可能不存在(允许 False Positive) D. 布隆过滤器出错了 ### Q3(进阶)— 考察核心原理 关于布隆过滤器的误判率公式 `p ≈ (1 - e^(-kn/m))^k`,其中 m 是位数组大小,n 是元素数量,k 是哈希函数个数。当 m/n = 10、k = 7 时,误判率约为: A. 50% B. 10% C. 0.8% D. 0.001% ### Q4(进阶)— 考察对比辨析 互斥锁方案和逻辑 TTL 方案用于防止缓存击穿,以下哪项对比是正确的? A. 互斥锁方案一致性弱但性能开销大 B. 逻辑 TTL 方案强一致且无锁开销 C. 互斥锁方案强一致但有死锁风险需要超时机制 D. 两者都能完全避免 DB 压力增加 ### Q5(深入)— 考察场景推理 某社交媒体平台的点赞数存储在 Redis 中,特点是不存在无效 key(key 都是有效的),但热点帖子点赞数的读取量极高(QPS 达数万)。对于这种场景,最有效的防击穿策略是: A. 布隆过滤器预加载所有有效 user_id B. 永不过期加后台异步刷新的逻辑 TTL 方案 C. 多层队列接力 DLX 重试模式 D. 将点赞数存入 MySQL 而不使用缓存 ### Q6(深入)— 考察源码级别细节 在完整的防御型缓存获取方法中,三道防线分别是什么顺序? A. 读缓存 → 布隆过滤器 → 分布式锁 B. 分布式锁 → 读缓存 → 布隆过滤器 C. 布隆过滤器 → 读缓存 → 分布式锁 D. 读缓存 → 分布式锁 → 布隆过滤器 --- ## 二、填空题(3道) ### F1 — 填空 根据布隆过滤器最优参数公式,当已知位数组大小 m 和元素数量 n 时,最优哈希函数个数 k = ______ × ln(2)。 > **提示**: 回顾公式中的关键变量关系。 ### F2 — 填空 雪崩的核心成因是大量 key 设置相同的过期时间,到期时 ______ ,请求洪水般涌向下游数据库。 > **提示**: 用一个两字词语描述这个状态变化。 ### F3 — 填空 互斥锁方案防止击穿的代码模式中,必须先做双重检查(Double Check):先尝试获取锁,成功后再从缓存读一次值,如果仍为 nil 才真正查 DB。这是因为其他线程可能已经在锁等待期间完成了重建。如果不做双重检查,会导致 ______ 。 > **提示**: 思考如果没有 double check 会重复执行什么操作。 --- ## 三、简答题(1道) ### S1 一个电商平台的商品 SKU 查询系统有以下特征: - SKU ID 的范围已知且相对稳定(约 100 万个有效 ID) - 查询流量不稳定,有时会出现恶意扫描 - 爆款商品单秒 QPS 可达 5000+ - 运营人员频繁更新商品价格信息 请设计一套三层防御方案来保护后端数据库,回答以下问题: 1. 每层使用什么技术?防护什么问题? 2. 第一层布隆过滤器的参数如何设置(m、n、k)? 3. TTL 随机化的具体参数建议是什么? > **答题框架提示**: > 1. 穿透/击穿/雪崩三层对应的技术方案 2. 布隆过滤器的参数计算 3. TTL 参数选择和理由 --- ## 参考答案与解析 ### 选择题答案 | 题号 | 正确答案 | 解析 | |------|---------|------| | Q1 | C | 缓存穿透的定义:恶意或异常查询不断访问数据库中不存在的 key,每次缓存 miss 导致请求直达 DB。A 是击穿;B 是雪崩;D 是热点 Key 问题。 | | Q2 | C | 布隆过滤器的特性:返回"一定不在"表示必定不存在(No False Negative),返回"可能存在"表示可能在(可能有 False Positive)。这是空间效率的代价。 | | Q3 | C | 当 m/n = 10、k = 7 时,误判率约 0.8%。这是面试常考的经典参数组合。增大 m/n 可进一步降低误判率(如 m/n = 20 时降至 0.02%)。 | | Q4 | C | 互斥锁方案保证强一致(新值写入后才可读到),但存在死锁风险——如果重建过程抛出异常没有释放锁,其他线程永远阻塞。必须用 defer unlock 或超时机制。B 错误——逻辑 TTL 是最终一致而非强一致。 | | Q5 | B | 点赞数几乎不可能穿透(key 都是有效的),重点防击穿。永不过期加后台异步刷新(逻辑 TTL)方案最合适——物理上不设过期时间,内存维护逻辑过期时间,发现过期后异步触发重建,读取到的仍是旧值(无脑 hit),直到新缓存写入成功。 | | Q6 | C | 正确的三层防线顺序:第1道——布隆过滤器拦截不存在的 key;第2道——读缓存命中直接返回;第3道——分布式锁防止击穿,只有一个线程查 DB 回填。这个顺序确保最轻量级的检查在最前面。 | ### 填空题答案 | 题号 | 答案 | 解析 | |------|------|------| | F1 | m/n | 最优哈希函数数 k = (m/n) * ln(2),此时误判率最低。ln(2) ≈ 0.693,所以 k 约等于 0.693 * m/n。 | | F2 | 集中失效 | 大量 key 同时过期意味着原本被缓存拦截的请求突然全部穿透到数据库,形成集中的查询洪峰,超出系统的承载能力。通过在 TTL 上加随机偏移可以分散过期时间点。 | | F3 | 重复查 DB / 重复重建 | 双重检查确保:即使成功获得锁,也要再读一次缓存——因为在这之前另一个已经持有锁的线程可能已完成重建并写回缓存。不做双重检查会浪费一次 DB 查询。 | ### 简答题参考答案 S1:**参考答案要点**: 1. 第一层——布隆过滤器:预加载所有 100 万有效 SKU ID,拦截不存在的 key 查询,防止穿透。第二层——互斥锁:对热点商品 sku 加分布式锁,防止击穿。第三层——TTL 随机化:设置基础 TTL 加减随机波动,防止雪崩。 2. 布隆过滤器参数:n = 100万,取 m/n = 10 则 m = 1000万位(约 1.2MB),k = 7。误判率约 0.8%,对业务可接受。也可取 m/n = 20 进一步降低到 0.02%。 3. TTL 随机化:商品价格在运营更新后立即写入 DB 并 DEL 缓存,下次读取时 SET 一个新的带随机抖动的 TTL。建议 baseMinutes=10, jitterPercent=30,使实际 TTL 落在 [7, 13] 分钟均匀分布。 **评分标准**:答出任意 2 个要点即可得满分;完全正确需覆盖三层防御方案、布隆参数计算和 TTL 策略三个维度。 ## 关联笔记 - [[03.Redis/strategies/多级缓存架构设计]] - [[03.Redis/strategies/旁路缓存与读写策略]] - [[03.Redis/strategies/HeavyKeeper 热点探测算法]]