Redis缓存穿透、击穿、雪崩:区别、识别与应对方案
【摘要】 一、三个问题的区别缓存是保护数据库的第一道防线,但使用不当会让压力瞬间压到数据库上。穿透、击穿、雪崩常被混淆,其实触发原因不同。缓存穿透:请求的数据在缓存和数据库中都不存在,例如恶意用 id=-1 反复查询商品。每次都会落到数据库,缓存形同虚设。缓存击穿:某个热点 key 恰好过期,大量并发请求同时发现缓存缺失,一起去查数据库。典型场景是秒杀商品详情页。缓存雪崩:大量 key 在同一时间集...
一、三个问题的区别
缓存是保护数据库的第一道防线,但使用不当会让压力瞬间压到数据库上。穿透、击穿、雪崩常被混淆,其实触发原因不同。
缓存穿透:请求的数据在缓存和数据库中都不存在,例如恶意用 id=-1 反复查询商品。每次都会落到数据库,缓存形同虚设。
缓存击穿:某个热点 key 恰好过期,大量并发请求同时发现缓存缺失,一起去查数据库。典型场景是秒杀商品详情页。
缓存雪崩:大量 key 在同一时间集中过期,或者 Redis 实例宕机,导致海量请求直接冲击数据库。
二、如何识别
- 数据库 QPS 突然飙升,而 Redis 命中率(keyspace_hits 与 keyspace_misses 之比)明显下降;
- 穿透:慢日志里出现大量查询结果为空的 SQL,且参数异常;
- 击穿:压力集中在个别 key,可用 redis-cli --hotkeys 排查热点;
- 雪崩:监控显示同一时间点过期的 key 数量陡增,或者 Redis 连接全部失败。
三、应对方案
1. 穿透
- 接口层做参数校验,非法 id 直接拦截;
- 对查询为空的结果缓存一个空值,TTL 设置为 60 秒左右;
- 使用布隆过滤器,启动时把所有合法 id 加载进去,不存在的请求直接返回。
2. 击穿
- 热点数据设置逻辑过期,由后台线程异步刷新;
- 使用互斥锁,只允许一个线程重建缓存:
def get_item(item_id):
val = redis.get(f"item:{item_id}")
if val:
return val
if redis.set(f"lock:{item_id}", 1, nx=True, ex=10):
val = db.query(item_id)
redis.set(f"item:{item_id}", val, ex=600)
redis.delete(f"lock:{item_id}")
return val
time.sleep(0.05)
return get_item(item_id)
3. 雪崩
- 过期时间加随机值,例如 600 秒加上 0 到 120 秒的随机数,避免集中失效;
- Redis 采用主从加哨兵或者集群部署,保证高可用;
- 在应用层增加限流、熔断和降级,数据库前面再放一层本地缓存。
四、小结
穿透是查不存在的数据,击穿是单个热点过期,雪崩是大面积失效。线上建议组合使用:参数校验加布隆过滤器、热点互斥锁、随机过期时间,并持续监控命中率,才能让缓存真正稳定。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)