你有没有遇到过这样的情况:网站突然卡死、APP半天打不开,刷新十几次才勉强加载出首页?后台一查,Redis全挂了,数据库被瞬间打爆——这很可能就是缓存雪崩在作怪。
什么叫缓存雪崩?
简单说,就是大量缓存数据在同一时间过期,或者缓存服务(比如Redis)整体宕机,导致原本该走缓存的请求全涌向数据库,数据库扛不住直接拖垮整个系统。电商大促前、秒杀活动开始那几秒,最容易中招。
别慌,这几招马上能用
1. 过期时间加随机数
别让所有key都设成 expire 3600 这样整点过期。改成带随机偏移:
SET user:123 "{"name":"张三"}" EX 3600 PX 500实际代码里可以这样写(以Redis命令为例):EXPIRE key (3600 + random(1, 300)) // 多加1~5分钟随机过期时间这样哪怕批量写入,也不会集体“断气”。2. 缓存永不过期 + 后台异步更新
对读多写少的数据(比如城市列表、商品分类),干脆不设过期时间,而是靠应用层定时或监听变更来刷新缓存。用户查的时候永远有数据,后台悄悄更新,既没穿透也没雪崩风险。
3. 加一层互斥锁(Mutex Lock)
当发现缓存失效,不是所有请求都去查库,而是只放行第一个去加载,其余排队等结果。伪代码示意:
if (cache.get(key) == null) {
String lockKey = "lock:" + key;
if (redis.set(lockKey, "1", "NX", "EX", 5)) { // 加锁5秒
Object dbData = db.query(key);
cache.set(key, dbData, 3600);
redis.del(lockKey);
} else {
Thread.sleep(50); // 等一下再试
return getFromCache(key);
}
}4. 服务降级兜底
真崩了怎么办?提前配好降级策略:比如热搜榜查不到就显示上周榜单,商品详情页加载慢就先展示文字+默认图。用Nginx或网关层快速返回静态兜底页,比让用户一直转圈强得多。
5. 多级缓存 + 分片部署
别把鸡蛋全放一个Redis里。本地缓存(Caffeine)+ 分布式缓存(Redis集群)组合用;Redis本身也拆成多个实例,按业务分片,哪怕其中一台挂了,其他还能顶一阵。
顺手检查下你的环境
打开Redis控制台,跑这条命令看看有没有大量key快到期:
redis-cli --scan --pattern "*" | xargs -L 1000 redis-cli ttl | sort -n | head -20如果一堆结果是 1 或 0,赶紧去代码里加随机过期逻辑。缓存不是设上就完事,得像养绿植一样定期“浇水修剪”。平时多看一眼监控里的缓存命中率、超时率,比出事后再熬夜回滚强十倍。