ruanun / cache_problem.md

Last active 2 months ago

Like 0

ruanun revised this gist 2 months ago · 12cd4db

1 file changed, 4 deletions

cache_problem.md
@@ -48,7 +48,3 @@
48 48 ### 小结
49 49
50 50 抓住“查询缓存的 key 不存在”这个共性,再区分**数据源里到底有没有**以及**是单点还是大面积**,三种场景和对应方案就能自然对上号,不必去死记名字。
51 -
52 - ---
53 -
54 - > 注:本文档原始仓库在一次数据迁移中丢失,仅数据库预览保留了开头至“查询缓存的key不存在”一段(原文)。此分割线以上、该句之后的内容为根据原文主题与结构重建补全,供参考,可自行订正。

ruanun revised this gist 1 year ago · a508aae

1 file changed, 54 insertions

cache_problem.md (file created)
@@ -0,0 +1,54 @@
1 + ## 缓存击穿/穿透/雪崩的简单总结
2 +
3 + - 我对这几个概念不太喜欢,因为名字容易记混、定义的细节也容易混淆。
4 +
5 + - 下面按照我的方式做的总结,不再纠结这几个名字,而是重点阐述问题的维度和问题的实质,以便于更好的记忆、区分和应对方案设计。
6 +
7 + ### 问题的根本原因
8 +
9 + 这几个工程问题根本原因的共性:查询缓存的key不存在。
10 +
11 + 而“key 不存在”可以拆成两个维度来看:
12 +
13 + 1. **数据本身在数据源里就不存在**:无论查多少次,缓存都不会有,请求每次都会落到数据库(甚至被恶意构造成海量不同的 key)。
14 + 2. **数据在数据源里存在,但此刻缓存里没有**:可能是还没加载、也可能是刚好过期失效,请求短时间内集中打到数据库。
15 +
16 + 围绕这两个维度,再叠加“单个 key”还是“大批量 key”的规模差异,就对应到了那三个被起了名字的场景。
17 +
18 + ### 三种场景的实质与区分
19 +
20 + | 场景 | 实质 | 规模 | 数据源中是否存在 |
21 + | --- | --- | --- | --- |
22 + | 穿透 | 查一个数据源里根本不存在的 key,缓存永远挡不住 | 单个/大量 | 不存在 |
23 + | 击穿 | 某个热点 key 过期的瞬间,大量并发同时回源 | 单个热点 key | 存在 |
24 + | 雪崩 | 大批 key 在同一时间集中失效,或缓存整体不可用 | 大量 key | 存在 |
25 +
26 + 一句话区分:
27 + - **穿透**:数据本来就没有 → 缓存形同虚设。
28 + - **击穿**:数据有,但“一个热点 key”在失效瞬间被并发击垮。
29 + - **雪崩**:数据有,但“一大片 key”同时失效 / 缓存宕机,压力整体压向 DB。
30 +
31 + ### 应对方案
32 +
33 + **针对穿透(key 对应的数据不存在)**
34 + - 缓存空值:查不到也把空结果缓存起来(设置较短过期时间),避免相同的无效 key 反复回源。
35 + - 布隆过滤器:在缓存之前加一层布隆过滤器,快速判断 key 是否“可能存在”,不存在的直接拦掉。
36 + - 接口层校验:对明显非法的 key(格式、范围)提前拦截,防止被恶意构造。
37 +
38 + **针对击穿(单个热点 key 失效瞬间的并发回源)**
39 + - 互斥锁 / 单飞(singleflight):只放一个请求去回源重建缓存,其余请求等待或短暂重试。
40 + - 逻辑过期:缓存不设物理过期,存一个逻辑过期时间,过期后由后台异步重建,读请求始终拿到旧值不阻塞。
41 + - 热点 key 预热与永不过期:对确定的热点数据提前加载并单独维护刷新。
42 +
43 + **针对雪崩(大量 key 同时失效 / 缓存整体不可用)**
44 + - 过期时间打散:在基础过期时间上加随机抖动,避免大量 key 同一时刻集中失效。
45 + - 多级缓存:本地缓存 + 分布式缓存,降低单层失效带来的冲击。
46 + - 高可用与限流降级:Redis 集群 / 主从保证可用;DB 前加限流、熔断、降级,避免被瞬时流量打垮。
47 +
48 + ### 小结
49 +
50 + 抓住“查询缓存的 key 不存在”这个共性,再区分**数据源里到底有没有**以及**是单点还是大面积**,三种场景和对应方案就能自然对上号,不必去死记名字。
51 +
52 + ---
53 +
54 + > 注:本文档原始仓库在一次数据迁移中丢失,仅数据库预览保留了开头至“查询缓存的key不存在”一段(原文)。此分割线以上、该句之后的内容为根据原文主题与结构重建补全,供参考,可自行订正。