【高并发实战】Redis缓存穿透、击穿、雪崩:3大经典的“炸库”危机与自救指南

简介: 本文详解缓存穿透、击穿、雪崩三大问题:穿透是查不存在的数据,击穿是热点Key失效被高并发冲击,雪崩是大量Key同时过期或Redis故障。结合比喻与解决方案,助你彻底理解并防范数据库风险。

前言

我们引入 Redis 的初衷,是让它作为“防弹衣”挡在 MySQL 数据库前面,拦截大部分的读取请求。

但在高并发场景下,如果这层防弹衣破了(缓存失效)或者没防住(查询不存在的数据),海量的流量就会瞬间打到脆弱的数据库上,导致数据库 CPU 飙升甚至宕机。这就是我们常说的缓存穿透、缓存击穿、缓存雪崩

这三个词听起来很像,但成因和解决方法完全不同。今天一文帮你彻底厘清。


1. 缓存穿透 (Cache Penetration)

比喻: 你的防弹衣上全是洞,子弹直接穿过去打中身体。

  • 现象:
    用户想要查询一个数据,Redis 里没有,数据库里也没有。
    结果就是:每次请求都会穿过 Redis,去查一遍数据库,然后返回空。当有恶意攻击者利用脚本疯狂查询不存在的 ID(如 id=-1)时,数据库会被瞬间打垮。
  • 核心原因: 查询了根本不存在的数据。
  • 解决方案:
  • 方案 A:缓存空值 (Cache Null Value)当数据库没查到时,我们也往 Redis 里存一个 null 或空字符串,并设置一个较短的过期时间(比如 30秒)。
  • 优点: 实现简单。
  • 缺点: 消耗内存(如果攻击者随机生成无数个 ID)。
  • 方案 B:布隆过滤器 (Bloom Filter) —— 推荐
    在访问 Redis 之前,先加一道屏障。布隆过滤器能通过极小的内存判断“某样东西一定不存在或可能存在”。
    如果布隆过滤器判定 ID 不存在,直接拦截,根本不让请求碰 Redis 和数据库。

2. 缓存击穿 (Cache Breakdown)

比喻: 防弹衣上某一个点(比如心脏部位)破了个洞,狙击手盯着这个点打。

  • 现象:
    某一个热点 Key(比如微博热搜第一名的 ID),在不停地扛着大并发。
    突然,这个 Key 的过期时间到了。
    就在缓存失效的这一瞬间,成千上万的请求同时涌入,发现 Redis 没数据,全部冲向数据库。数据库瞬间被单一的热点数据压垮。
  • 核心原因: 单一热点 Key 过期 + 高并发
  • 解决方案:
  • 方案 A:互斥锁 (Mutex Lock)当发现 Redis 没数据时,不要所有人一窝蜂去查数据库。大家排队,只让第一个人去查,查到了写回 Redis,后面的人直接读 Redis。
  • 代码逻辑: 使用 SETNX 获取锁。
  • 方案 B:逻辑过期 (Logical Expiration)
    物理上不设置过期时间(永不过期),但在 Value 内部存一个时间戳。查询时检测到时间戳过期了,异步开启一个线程去更新数据,当前请求先返回旧数据。

3. 缓存雪崩 (Cache Avalanche)

比喻: 雪崩发生了,整片山坡的雪同时塌下来。

  • 现象:
    Redis 中大量的 Key 在同一时刻集体过期。
    或者,Redis 节点直接宕机了。
    结果是:原本被 Redis 拦截的海量请求,瞬间全部转移到数据库,导致数据库像被雪崩淹没一样挂掉。
  • 核心原因: 大量 Key 同时过期Redis 故障
  • 解决方案:
  • 方案 A:随机过期时间 (Random TTL)在设置过期时间时,不要都设为 1小时。而是在 1小时的基础上,加上一个随机数(比如 1-10 分钟)。这样 Key 就会分散过期,不会扎堆。
  • 公式: Expire_Time = Base_Time + Random(Value)
  • 方案 B:高可用架构
    部署 Redis 哨兵(Sentinel)或 集群(Cluster),防止单点故障导致全盘皆输。
  • 方案 C:限流与降级
    在网关层做限流,或者当数据库压力过大时,直接开启降级模式(返回默认值或“系统繁忙”),保住数据库一命。

总结:一张表看懂区别

问题 关键特征 根本原因 核心解决方案
缓存穿透 不存在的数据 数据源和缓存都没有 布隆过滤器、缓存空对象
缓存击穿 单个热点 Key 失效 局部并发过大 互斥锁、逻辑过期
缓存雪崩 大量 Key 同时失效 整体并发压力转移 随机过期时间、Redis高可用

口诀记忆:

  • 穿透:查无此人。
  • 击穿:盯着一点打。
  • 雪崩:全线崩盘。
相关文章
|
2月前
|
存储 NoSQL Java
扛住百万级 QPS:高并发架构核心三板斧全解
本文系统阐述高并发架构三大核心支柱:流量削峰(前端拦截、网关限流、应用缓冲、分布式限流)、异步化(本地CompletableFuture与RocketMQ分布式解耦)及水平扩展(无状态化、服务注册发现、读写分离与分库分表),并以秒杀系统为例实战整合,兼顾避坑指南与概念辨析。
435 3
|
1月前
|
开发框架 Java 数据库连接
一张图讲完Java 30年发展史,看完彻底搞懂版本演进
这篇Java版本演进指南,用一天时间理清30年发展脉络:从JDK 1.0“一次编写,到处运行”,到JDK 8函数式革命(Lambda/Stream),再到JDK 17/21 LTS新标配(var/record/虚拟线程)。帮你告别版本困惑,读懂面试考点,选对生产版本。
一张图讲完Java 30年发展史,看完彻底搞懂版本演进
|
设计模式 前端开发 JavaScript
Spring MVC(一)【什么是Spring MVC】
Spring MVC(一)【什么是Spring MVC】
|
运维 监控 Devops
什么是 DevOps?看这一篇就够了!
什么是 DevOps?看这一篇就够了!
1126 1
|
存储 监控 Java
10分钟3个步骤集成使用SkyWalking
此时就非常推荐SkyWalking了,SkyWalking不仅仅是一款链路跟踪工具,还可以作为一个系统监控工具,还具有告警功能。使用简便、上手又快。真可谓快、准、狠。
10分钟3个步骤集成使用SkyWalking
|
2月前
|
存储 缓存 NoSQL
吃透 Redis 核心原理:内存模型、数据结构与持久化,从根上解决 90% 线上问题
本文深入剖析Redis三大核心基石:内存模型(含内存划分、碎片优化、过期与淘汰策略)、底层数据结构(String/Hash/List/Set/ZSet及扩展结构)和持久化机制(RDB/AOF/混合持久化),助开发者从set/get表层用法进阶到根因级问题解决。
423 2
|
5月前
|
监控 Java Sentinel
Sentinel安装与集成
介绍如何切换hmall-micro项目至dev_02分支并提交代码,强调多分支并行开发模式。随后讲解Sentinel服务保护框架的安装与配置,包括控制台部署、本地运行及项目集成,实现微服务熔断降级,并通过簇点链路监控接口。
Sentinel安装与集成
|
2月前
|
XML Java 数据安全/隐私保护
彻底搞懂 Spring Boot 自动配置原理:从源码拆解到手写 Starter,零废话全干货
本文深入解析SpringBoot自动配置原理,基于SpringBoot 3.4.2版本详细拆解了自动配置的执行流程。主要内容包括:1)自动配置的本质是基于条件注解的动态JavaConfig配置类;2)核心执行流程通过AutoConfigurationImportSelector实现;3)SpringBoot 3.x采用新的自动配置注册方式;4)重点讲解了@Conditional系列条件注解的使用场景与常见坑点;5)通过开发自定义加密Starter实战演示完整实现过程。
1258 3
|
5月前
|
运维 Shell 应用服务中间件
【速查手册】Docker常用命令大全:这20%的命令解决了80%的问题
本文精炼总结 Docker 高频命令,按镜像管理、容器生命周期、排查调试、清理维护四大场景分类,详解常用参数与实战示例,附速查表,助你高效掌握核心操作,提升开发运维效率。