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

相关推荐
暴躁小师兄数据学院19 小时前
【AI大数据工程师特训笔记】第01讲:数据库基本概念
大数据·数据库·笔记
杨云龙UP19 小时前
Oracle Flashback Query 实战练习:误更新、误删除数据如何快速找回?
linux·运维·数据库·sql·oracle·flashback
basketball61619 小时前
SQL 条件聚合 使用方法总结
服务器·数据库·sql
洛水水19 小时前
Redis 内存淘汰策略详解
数据库·redis·缓存
一只fish19 小时前
Oracle官方文档翻译《Database Concepts 26ai》第12章-数据并发与一致性
数据库·oracle
Crazy_eater19 小时前
Mysql(1)
数据库·mysql
Mr. zhihao19 小时前
Redis 集群分区思想的演进:从哈希取余到虚拟槽
redis·哈希算法
万岳科技系统开发19 小时前
外卖系统小程序开发方案解析:直播、团购与外卖功能如何融合
数据库·小程序·架构