redis缓存:雪崩、穿透、击穿详解

一、缓存三兄弟

1. 缓存雪崩(Cache Avalanche)

问题描述:

大量的缓存数据在同一时间集中失效,此时请求全部打到MySQL,造成MySQL崩溃或响应能力降低。

场景还原:

  • Redis最初是空的,需要预热
  • 大量缓存数据设置了相同的过期时间
  • Redis重启或MySQL/存储系统重启后,缓存空窗期请求全打MySQL

解决方案:

方案 说明
间隔设置过期时间 给缓存的过期时间加上随机偏移量,避免同一时间批量失效
数据预热 系统启动或重启后,提前将热点数据加载到Redis
持久化 开启Redis持久化,避免重启后缓存全空
多级缓存 引入本地缓存作为缓冲层

2. 缓存穿透(Cache Penetration)

问题描述:

查询的数据在缓存和MySQL中都不存在,请求穿透缓存直接打MySQL,如果大量恶意请求,可能导致MySQL崩溃。

场景还原:

  • 查询一个根本不存在的key
  • 恶意请求大量不存在的数据
  • MySQL成为最后一道防线,不断被无效查询击穿

解决方案:

方案 说明
缓存空值 对不存在的数据在Redis中缓存一个空值(nil标记),下次查询直接返回
布隆过滤器(Bloom Filter) 概率型数据结构,判断某个key一定不存在,存在则可能误判

布隆过滤器部署位置对比:

部署位置 优点 缺点
部署在Server端 轻量级实现 多个Server端需要初始化多个布隆过滤器,运维压力大
部署在Redis 共享一份布隆过滤器,多个Server共用 需要额外的Redis插件支持

3. 缓存击穿(Cache Breakout)

问题描述:

某个热点key在Redis中没有数据,但MySQL中有数据。大量的并发请求同时访问Redis发现没有该数据,转而全部去请求MySQL,造成MySQL崩溃。

场景还原:

  • 热点key刚好过期
  • 大量并发请求同时发现Redis没数据
  • 所有请求同时打向MySQL

解决方案:

方案 说明
分布式锁 确保只有一个请求去查MySQL,其他请求等待结果
过热数据永不过期 对极热点数据设置永不过期或后台异步续期

二、缓存架构设计

1. 整体架构

复制代码
                    +-------+
                    | Client |
                    +---+---+
                        |
                        v
+----------------+   +-------+   +------------+   +-------+
|   Write Path   |->| Redis |   | Read Path  |<---| MySQL |
+----------------+   +-------+   +------------+   +-------+
      |                              ^
      |                              |
      v                              |
+----------------+                   |
|    MySQL       |-------------------+
+----------------+

  同步中间件(伪装成MySQL从库)

2. 读写策略

读策略流程:

复制代码
Client -> Redis存在? -> Yes -> 直接返回数据
              |
              No
              v
         查MySQL -> 有数据 -> 写入Redis -> 返回数据
                   |
                   No
                   v
              返回空/错误

写策略流程:

复制代码
Client -> 写Redis(设置过期时间) -> 写MySQL
              |
              v (等待MySQL同步到Redis)
         过期时间 = Server到MySQL同步时间 + 中间件拉取数据时间 + 传输时间
              |
              v (通常设定200ms经验值)

3. 同步中间件

核心职责:

  • 伪装成MySQL从数据库
  • 同时连接MySQL和Redis
  • 拉取MySQL的binlog变更
  • 将热点数据同步给Redis

三、缓存一致性问题

脏数据问题

场景:

写Redis成功,但写MySQL失败,此时会有约200ms的脏数据时间窗口。

时间线:

复制代码
T=0ms   Client写Redis成功
T=50ms  Client开始写MySQL
T=200ms 中间件同步MySQL到Redis
        |
        v (中间T=0ms~T=200ms是脏数据窗口)

数据一致性保证

策略 说明
先写Redis再写MySQL 保证最终一致性,有短暂脏数据窗口
过期时间兜底 即使同步失败,脏数据也会在过期后自动清除
延迟双删 写完MySQL后删除Redis,再延迟一段时间后删除

四、安全性问题汇总

问题 原因 解决方案
写Redis成功写MySQL失败 网络抖动/MySQL响应慢 过期时间兜底+告警机制
Redis数据丢失 Redis重启/故障 开启持久化(RDB/AOF)
缓存雪崩 大量key同时过期 随机过期时间+数据预热
缓存穿透 查询不存在的数据 空值缓存+布隆过滤器
缓存击穿 热点key过期+并发 分布式锁+永不过期

根据零声教育教学写作https://github.com/0voice

相关推荐
IronMurphy17 小时前
【算法五十七】146. LRU 缓存
算法·缓存
茉莉玫瑰花茶17 小时前
综合案例 - AI 智能租房助手 [ 5 ]
服务器·数据库·人工智能·python·ai
ywl47081208717 小时前
jwt生产token,简单版helloworld
java·数据库·spring
器灵科技17 小时前
AI视频工具实测:Seedance/可灵/HappyHorse谁最能打?
java·运维·数据库·人工智能·github
huangdong_18 小时前
京东商品图片视频批量下载与m3u8视频合并技术完整实现方案
大数据·前端·数据库
倒流时光三十年18 小时前
PostgreSQL CASE 条件表达式详解
数据库·postgresql
字节跳动数据平台18 小时前
营销视频进入工业化时代,火山引擎多模态数据湖如何助力多米实现内容生产提效 100+ 倍
数据库
健康平安的活着18 小时前
mysql中数据库脚本太大,通过脚本命令修改db名称
数据库·mysql
伊甸319 小时前
从企业级项目学敏感词过滤:DFA算法与双层缓存实战
java·算法·缓存
倒流时光三十年19 小时前
PostgreSQL COALESCE 条件表达式函数详解
数据库·postgresql