缓存穿透、缓存击穿、缓存雪崩的区别与解决方案
1. 缓存穿透(Cache Penetration)
- 定义:请求访问数据库中不存在的数据,导致缓存层无法命中,流量直接穿透到数据库。
- 常见场景:恶意攻击(如频繁请求不存在的用户ID)、参数非法(如负数ID)。
解决方案:
布隆过滤器(Bloom Filter):
在缓存层前加一层布隆过滤器,预存所有合法Key的哈希值。请求到达时,先检查布隆过滤器:- 若不存在,直接拦截请求,返回空。
- 若存在,再查询缓存或数据库。
- 缓存空值(Cache Null):
对查询结果为空的Key,缓存一个短期的占位符(如NULL:5min
),避免重复穿透。 - 参数校验:
拦截非法请求(如非数字ID、超出业务范围的参数),减少无效查询。
2. 缓存击穿(Cache Breakdown)
- 定义:热点Key突然失效时,大量并发请求直接冲击数据库,导致数据库瞬时压力激增。
- 常见场景:促销活动中的热门商品信息、突发新闻。
解决方案:
互斥锁(Mutex Lock):
当缓存失效时,通过分布式锁(如Redis的SETNX
)让一个线程重建缓存,其他线程等待锁释放后重试。String data = redis.get(key); if (data == null) { if (redis.setnx(lockKey, "1", 3, TimeUnit.SECONDS)) { data = db.queryData(); redis.set(key, data, 30, TimeUnit.MINUTES); redis.delete(lockKey); } else { Thread.sleep(100); // 短暂等待后重试 return getData(key); } }
- 永不过期(Logical Expiration):
对热点Key设置物理永不过期,通过后台异步线程定期更新缓存,保证数据新鲜度。 - 熔断降级:
在缓存失效期间,启用降级策略(如返回默认值或静态页面),保护数据库。
3. 缓存雪崩(Cache Avalanche)
- 定义:大量缓存Key在同一时间过期,导致请求集中访问数据库,引发系统崩溃。
- 常见场景:批量缓存初始化后同时过期、定时任务集中刷新缓存。
解决方案:
- 随机过期时间:
在基础过期时间上增加随机值(如基础时间 + random(0~300s)
),分散Key失效时间。 - 多级缓存(Multi-Level Cache):
结合本地缓存(如Caffeine)和分布式缓存(如Redis)。当Redis失效时,本地缓存仍可短暂兜底。 - 服务熔断与限流:
使用Sentinel或Hystrix在缓存失效期间限制数据库访问的并发量,避免过载。
- 随机过期时间:
Redis大Key与大Value问题及解决方案
1. 大Key(Big Key)
- 定义:单个Key的Value大小超过1MB,或包含大量元素(如Hash/List有10万条记录)。
风险:
- 阻塞主线程:大Key的读写操作耗时高,影响Redis响应速度。
- 内存不均:导致集群中某些节点内存占用过高,触发OOM。
解决方案:
拆分Key:
- Hash分片:将大Hash拆分为多个小Hash,如
user:1000:info
→user:1000:info:1
、user:1000:info:2
。 - List分页:按范围分片存储(如
list:1000:0-1000
、list:1000:1001-2000
)。
- Hash分片:将大Hash拆分为多个小Hash,如
- 异步删除:
使用UNLINK
命令代替DEL
,非阻塞删除大Key。 - 压缩存储:
对JSON等文本数据使用压缩算法(如GZIP),减少内存占用。
2. 大Value(Big Value)
- 定义:单个Value的大小超过10MB。
风险:
- 网络延迟:传输大Value消耗带宽,影响其他请求的响应时间。
- 持久化阻塞:RDB/AOF时大Value可能导致持久化延迟。
解决方案:
优化数据结构:
- 使用更紧凑的结构(如用HyperLogLog替代Set统计UV)。
- 避免存储冗余数据(如仅存ID而非完整对象)。
- 分片存储:
将大Value拆分为多个小Key,客户端合并处理。 - 外部存储:
将大Value存储到文件系统(如HDFS),Redis中仅存访问路径。
实际案例与监控手段
案例1:缓存穿透防御
在金融平台的风控系统中,攻击者频繁请求不存在的用户ID,导致数据库负载飙升。通过引入布隆过滤器(预存所有有效用户ID哈希)和空值缓存(设置5分钟过期),穿透请求减少99%。
案例2:大Key优化
某电商平台的商品评论列表(List类型)包含50万条记录,导致LRANGE
操作耗时超过1秒。通过分片存储(每片1000条)和按需加载(仅查询前N页),响应时间降至50ms。
监控与工具
- Redis慢查询日志:通过
slowlog get
命令分析耗时操作,定位大Key。 - 内存分析工具:使用
redis-rdb-tools
分析RDB文件,识别内存占用高的Key。 - 告警配置:对Key大小、内存使用率设置阈值告警(如Prometheus+Alertmanager)。
总结
缓存问题:
- 穿透 → 布隆过滤器 + 空值缓存。
- 击穿 → 互斥锁 + 永不过期策略。
- 雪崩 → 随机过期 + 多级缓存。
大Key/Value:
- 拆分、压缩、异步删除。
核心原则:
- 预防优于修复:在业务设计阶段规避大Key。
- 监控常态化:通过工具及时发现并优化异常Key。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。