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

相关推荐
数智化管理手记15 小时前
主数据重复、错漏频发?一站式主数据管理平台如何落地?
大数据·运维·数据库·人工智能·数据挖掘
吴声子夜歌15 小时前
MongoDB 4.2——选择片键
数据库·mongodb
天天进步一点点16 小时前
QSqlQuery删除sqlite数据库执行drop数据表报错database table is locked unable to fetch row问题
数据库·oracle·sqlite
音视频工程实战16 小时前
PromptQL 新手入门与实战指南
数据库·sql·算法
清川渡水16 小时前
NL2SQL 的正确打开方式:从「AI 猜 SQL」到「置信度闭环」的工程化落地
数据库·人工智能·sql
TDengine (老段)16 小时前
TDengine Go 与 Rust 连接器 — 高性能异步访问
大数据·数据库·物联网·golang·rust·时序数据库·tdengine
东方佑17 小时前
MA-RMSNorm:打破“缩放换智能”的魔咒,大模型归一化的一次范式革命!
数据库·人工智能·计算机视觉
云和恩墨17 小时前
「云帆计划·长沙站」活动成功举办,云和恩墨与紫薇垣和湖南金悦科技分别签约并授牌,本地伙伴生态建设加速
数据库·科技
千维百策66618 小时前
如何管理错误预算:提升服务可靠性与 SLO 达成率的实践经验
服务器·网络·数据库
Y38153266219 小时前
2026 年 7 月,SERP API 调用的稳定性实战:超时、重试、降级
开发语言·数据库·人工智能·php