redis缓存三兄弟
在 Redis 缓存体系中,“缓存三兄弟” 通常指的是缓存穿透、缓存击穿和缓存雪崩,这三个是缓存场景中常见的典型问题,会严重影响系统性能甚至导致服务崩溃。以下是对它们的详细解析:
1、缓存穿透
问题描述
- 场景:客户端请求不存在于缓存和数据库中的数据,导致请求直接穿透缓存层,每次都访问数据库。
- 危害:大量无效请求会压垮数据库,甚至引发DDoS 攻击。
成因
- 恶意攻击:攻击者故意请求不存在的键(如随机字符串)。
- 业务逻辑漏洞:如用户输入非法参数,查询不存在的数据。
解决方案
-
布隆过滤器(Bloom Filter)
- 原理:在请求进入数据库前,用布隆过滤器快速判断数据是否存在。若不存在,直接拒绝请求,避免穿透到数据库。
- 适用场景:数据基数大、更新频率低的场景(布隆过滤器更新成本较高)。
-
空值缓存
- 原理:当查询结果为 null 时,仍将空值存入缓存(设置较短过期时间,如 5 分钟),避免相同请求反复查询数据库。
- 注意:需设置合理过期时间,防止缓存大量无效数据。
-
参数校验
- 对请求参数进行合法性校验(如 ID 格式、范围限制),提前拦截无效请求。
2、缓存击穿
问题描述
- 场景:热点数据的缓存过期瞬间,大量请求同时访问数据库,导致数据库压力激增。
- 关键词:单个热点键、缓存过期、并发请求。
成因
- 热点数据(如秒杀商品、热门新闻)的缓存设置了固定过期时间,到期时大量用户请求同时到达。
解决方案
-
热点数据永不过期
- 不设置过期时间,通过其他机制(如异步线程)主动更新缓存(需注意数据一致性)。
-
加互斥锁(Mutex)
- 原理:当缓存失效时,仅允许单个请求访问数据库并重建缓存,其他请求等待锁释放后从缓存获取数据。
- 实现方式:
- 使用 Redis 的
SET NX
命令实现分布式锁(如set lock_key unique_value nx px 10000
)。 - 注意设置锁的过期时间,避免死锁。
- 使用 Redis 的
-
提前更新缓存
- 在缓存过期前(如剩余 10% 时间),异步提前刷新缓存,避免到期时被动重建。
3、缓存雪崩
问题描述
- 场景:大量缓存键同时过期或Redis 服务宕机,导致大量请求直接涌入数据库,造成数据库负载过高甚至崩溃。
- 关键词:大量键过期、缓存不可用、请求激增。
成因
- 批量缓存设置了相同或相近的过期时间,到期时集体失效。
- Redis 集群故障(如主从切换、节点宕机),导致缓存服务整体不可用。
解决方案
-
分散过期时间
- 在设置缓存过期时间时,添加随机时间偏移(如
TTL = 3600 + random(600)
),避免大量键同时过期。
- 在设置缓存过期时间时,添加随机时间偏移(如
-
提升缓存高可用性
- 采用 Redis 集群(Cluster)或主从复制(Master-Slave)架构,结合 Sentinel 实现自动故障转移,减少单点故障影响。
-
熔断降级
- 通过熔断器(如 Hystrix、Resilience4j)监控数据库负载,当压力超过阈值时,直接返回预设的默认值或提示信息,保护数据库。
-
限流
- 通过限流组件(如 Guava RateLimiter、Redis 限流)限制单位时间内的请求量,避免突发流量压垮系统。
-
二级缓存
- 使用本地缓存(如 Caffeine、Ehcache)作为一级缓存,Redis 作为二级缓存,降低对 Redis 的依赖。
4. 三兄弟对比总结
问题 | 核心原因 | 典型场景 | 解决方案核心思路 |
---|---|---|---|
缓存穿透 | 请求不存在的数据 | 恶意攻击、非法参数查询 | 过滤无效请求、缓存空值 |
缓存击穿 | 单个热点键过期,并发请求 | 热点商品秒杀、突发流量 | 避免并发重建、延长热点键存活 |
缓存雪崩 | 大量键过期或缓存服务不可用 | 批量缓存到期、Redis 宕机 | 分散过期时间、增强系统容错 |