Files

151 lines
7.5 KiB
Markdown
Raw Permalink Normal View History

2026-08-09 19:06:40 +08:00
---
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 热点探测算法]]