[TOC] #### 1. 前言 --- 我们做的网站上线了,Redis 缓存也配好了,一切看起来很美好 突然有一天,有人恶意构造了一批不存在的 user_id,疯狂请求接口 每次请求,Redis 里没有,MySQL 里也没有,缓存形同虚设,请求全部打到数据库,MySQL CPU 飙到 100%,网站挂了 这就是缓存穿透 #### 2. 问题本质 --- 正常流程:请求 → Redis 没有 → 查 MySQL → 存回 Redis → 返回 穿透:请求的 key 本来就不存在,Redis 永远没有,MySQL 也永远没有,每次请求都穿透缓存,直达数据库 #### 3. 方案一:缓存空值 --- 查不到也存一份空值: ```bash set user:9999999 "" ex 60 ``` 下次再查 user:9999999,Redis 直接返回空,不碰 MySQL,简单有效 但如果大量不同的不存在 key 被请求,Redis 里会存一堆空值,浪费内存,所以空值的过期时间别太长 #### 4. 方案二:布隆过滤器 --- 在 Redis 前面加一层布隆过滤器,请求来了先问它:这个 key 可能存在吗? + 不存在 → 直接返回,Redis 和 MySQL 都不用查。 + 可能存在 → 继续正常流程 布隆过滤器第22讲会详细讲,这里知道它能挡掉 “明显不存在的请求” 就行 #### 5. 方案三:参数校验 --- 接口层先做基本校验,这是第一道防线,成本最低 + user_id 是负数?直接返回,不用查 + user_id 格式不对?直接返回 三道防线配合:参数校验 → 布隆过滤器 → 缓存空值,层层过滤,穿透基本挡住了 #### 6. 本文小结 --- 小总结: + 穿透:key 不存在,请求直达 MySQL + 缓存空值:简单,但浪费内存 + 布隆过滤器:高效,需要预热 + 参数校验:第一道防线 + 三道防线配合,穿透基本挡住了