Redis 缓存穿透、击穿、雪崩的区别与解决方案
什么是缓存穿透?
缓存穿透是指查询一个一定不存在的数据,由于缓存不命中,每次都要查数据库,失去了缓存的意义。
解决方案
- 布隆过滤器:将所有可能存在的数据哈希到一个足够大的 bitmap 中
- 缓存空值:如果查询返回空,把空结果也缓存起来
python
def get_user(user_id):
cache_key = f"user:{user_id}"
result = redis.get(cache_key)
if result is not None:
return json.loads(result) if result != "NULL" else None
user = db.query("SELECT * FROM users WHERE id = %s", user_id)
if user:
redis.setex(cache_key, 3600, json.dumps(user))
else:
redis.setex(cache_key, 300, "NULL")
return user
什么是缓存击穿?
缓存击穿是指一个热点 key 过期的瞬间,大量请求直接打到数据库。
解决方案
- 互斥锁:用 SETNX 加锁,只让一个请求去查数据库
- 永不过期:热点 key 不设过期时间,异步更新
什么是缓存雪崩?
缓存雪崩是指大面积的 key 同时过期,导致所有请求涌向数据库。
解决方案
- 随机过期时间:在基础过期时间上加随机值
- 多级缓存:L1 本地缓存 + L2 Redis 缓存
- 限流降级:数据库前面加限流保护
三者对比
| 问题 | 触发条件 | 影响范围 | 核心解决思路 |
|---|---|---|---|
| 穿透 | 查询不存在的数据 | 单个 key | 布隆过滤器 + 缓存空值 |
| 击穿 | 热点 key 过期 | 单个热点 key | 互斥锁 + 永不过期 |
| 雪崩 | 大面积 key 过期 | 所有 key | 随机过期 + 多级缓存 |
更多数据库技术文章,请访问 ora100.com