java - redis 缓存雪崩

缓存雪崩的两种场景

实际开发中,缓存雪崩分两种完全不同的诱因,解决方案也完全不同,必须分开处理。

场景1:大面积缓存key同时过期(最常见)

开发时给大量缓存设置了相同的过期时间,到了时间点所有key集中失效,瞬间所有读请求都绕过Redis,直接查询数据库。

场景2:Redis实例整体不可用(高风险)

Redis服务本身宕机、断网、内存溢出OOM、被误操作关停等,导致整个缓存层彻底不可用,所有请求直接穿透到数据库。

解决方案

1. 针对「大面积key同时过期」的解决方案

核心思路是打散过期时间,避免集中失效 。

不给同一批数据设置完全相同的过期时间,在基础时间上加一个随机值,把过期时间打散。

java 复制代码
"错误写法:统一1小时过期,容易集中失效"
redisTemplate.opsForValue().set("product:" + productId, product, 3600, TimeUnit.SECONDS);


"正确写法:基础1小时 + 0~300秒随机偏移,错开过期"
int baseTime = 3600;
int randomOffset = new Random().nextInt(300);
redisTemplate.opsForValue().set("product:" + productId, product, baseTime + randomOffset, TimeUnit.SECONDS);

这样所有商品的过期时间分布在59~65分钟之间,不会出现同一时间几万条key同时过期的情况。

2. 分级缓存策略

按数据热度设置不同的过期时间,热点数据长过期/永不过期,冷数据短过期,从根源上减少同时过期的量级。

  • 热点数据(如首页Top100商品、分类导航):设置1天过期,后台异步定时更新,永不过期
  • 普通数据(如普通商品详情):1小时+随机偏移
  • 冷数据(如冷门商品、历史订单):10分钟,过期了也不会有大量请求

3. 缓存预热 + 定时刷新

不要等用户请求触发缓存加载,系统启动或低峰期提前把热点数据加载到缓存;

并且通过定时任务分批异步刷新 缓存,而不是等过期后由用户请求重建。

比如,电商大促前,用脚本提前把所有活动商品缓存写入Redis,过期时间错落设置;凌晨2点低峰期,分批刷新全量商品缓存,避免白天高峰期缓存失效。

开发避坑总结

  1. 永远不要给批量缓存设置完全相同的过期时间,加随机偏移是成本最低的防雪崩手段
  2. 生产环境Redis必须集群部署,禁止单节点
  3. 核心业务一定要做二级缓存(本地 + 远程)和熔断降级,给自己留兜底
  4. 做好监控:Redis命中率、过期key数量、数据库QPS/CPU,这几个指标是雪崩的"预警灯"
  5. 上线前做压测:模拟缓存集中失效、Redis宕机的场景,验证系统的抗压能力
相关推荐
步行cgn2 分钟前
Spring MVC POST 请求乱码:原因与完整解决方案
java·spring·mvc
y1su3 分钟前
Leetcode 链表,树,回溯 模板
java·leetcode·链表
qianyuqiye18 分钟前
K8s 命名空间与 Pod 入门:从概念到实战
java·docker·kubernetes
牧瀬クリスだ16 分钟前
观察者模式:一个对象变化,一群对象自动响应
java·观察者模式·设计模式
小张成长计划..20 分钟前
【Linux】26:线程互斥和同步
java·开发语言
邪修king3 小时前
Re:Linux 系统篇(三十五):进程间通信Chapter2:从匿名管道到进程池:Linux 进程间通信实战(深度理解「先描述,再组织」)
java·linux·运维
拆房老料3 小时前
【第四部分:Agentic 智能体设计模式】16. 一个 Prompt 搞不定复杂任务?试试 Prompt Chaining
java·前端·人工智能·设计模式·prompt
张张123y4 小时前
后端第十四课:Agent 记忆系统(让 Agent 记住上下文和用户,跨会话不健忘)
java·大数据·人工智能·python·agent·记忆
曹牧9 小时前
C#:空合并运算符
java·前端·数据库
布吉岛的石头9 小时前
Java 程序员第 50 阶段2:预训练的目标函数:自回归语言建模本质
java·开发语言·人工智能·深度学习·回归·transformer