一、缓存三兄弟
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