用「银行防盗系统」类比理解缓存问题
一、缓存穿透(查无此人攻击)
场景:黑客伪造不存在的账户ID频繁查询
类比:小偷用假身份证到银行金库门口反复试开锁
请求 → 缓存 → 不存在 → 数据库 → 不存在(每次穿透)
解决方案:
- 布隆过滤器(门禁白名单)
// 初始化过滤器 BloomFilter<String> filter = BloomFilter.create(1000000); // 预热合法ID validIds.forEach(filter::put);// 查询前校验 if(!filter.mightContain(id)) return null;
- 空值缓存(记录黑名单)
redisTemplate.opsForValue().set(id, "NULL", 5, TimeUnit.MINUTES);
二、缓存击穿(爆破热点数据)
场景:百万用户同时访问刚过期的爆款商品
类比:劫匪在运钞车到达前瞬间集体冲击金库
缓存失效 → 大量请求涌入数据库
解决方案:
- 互斥锁(武装押运)
public Object getData(String key) {Object value = redis.get(key);if (value == null) {if (redis.setnx(key+"_lock", "1")) { // 抢锁value = db.query(key); // 查库redis.set(key, value, 30, TimeUnit.MINUTES);redis.del(key+"_lock");} else {Thread.sleep(100); // 重试return getData(key);}}return value; }
- 逻辑过期(延长押运时间)
// 缓存值包含过期时间 class CacheData {Object data;long expireTime; } // 异步更新缓存
三、缓存雪崩(系统性崩溃)
场景:双十一零点大量缓存同时失效
类比:全城银行同时断电导致安防系统瘫痪
缓存层崩溃 → 数据库被流量击垮 → 服务不可用
解决方案:
- 随机过期时间(错峰维护)
int randomTime = 30 + new Random().nextInt(15); // 30-45分钟 redisTemplate.opsForValue().set(key, value, randomTime, TimeUnit.MINUTES);
- 二级缓存(备用电源)
// Ehcache本地缓存 + Redis分布式缓存 @Cacheable(cacheNames = "user", key = "#id",cacheManager = "ehcacheManager") public User getUser(int id) { /*...*/ }
- 熔断降级(应急通道)
// 使用Hystrix熔断 @HystrixCommand(fallbackMethod = "getDefaultData") public Object getHotData(String key) { /*...*/ }
四、防御系统对比表
攻击类型 | 类比场景 | 防御策略 | 监控指标 |
---|---|---|---|
穿透 | 假身份试开锁 | 布隆过滤器 + 空值缓存 | cache_miss_rate↑↑ |
击穿 | 集中爆破金库 | 互斥锁 + 逻辑过期 | qps_spike_detect |
雪崩 | 全城安防瘫痪 | 随机过期 + 熔断降级 | db_connection_pool↑ |
五、生产环境组合拳
电商系统示例:
- 接入层:Nginx限流(每秒5000请求)
- 服务层:Guava本地缓存 + Redis集群
- 存储层:MySQL读写分离 + 队列削峰
Redis配置示例:
# 开启内存淘汰策略
maxmemory-policy volatile-ttl
# 设置连接超时防止雪崩
timeout 30
# 监控关键指标
redis-cli --latency-history -i 10
六、面试高频问题
Q1:布隆过滤器为什么不能删除数据?
- 位图共享:多个数据可能映射到同一位(误删他人钥匙)
- 解决方案:使用Counting Bloom Filter(但增加内存)
Q2:互斥锁造成死锁怎么办?
- 超时释放:
redis.setnx(key, "1", 10, TimeUnit.SECONDS)
- 守护线程:定期检测锁持有者是否存活
Q3:如何发现缓存雪崩前兆?
- 监控指标:
- 缓存命中率持续低于80%
- 数据库连接数突增
- Redis CPU使用率>90%
七、灾备演练方案
- 混沌工程:随机杀死Redis节点测试容错
- 压测工具:JMeter模拟百万QPS冲击
- 降级预案:
- 一级降级:关闭非核心服务
- 二级降级:返回静态默认数据
终极总结
缓存问题防御 = 银行安全体系
- 穿透防御:严格身份核验(布隆过滤器)
- 击穿防御:重点目标保护(互斥锁)
- 雪崩防御:分散风险策略(随机过期)
记住这个公式:预防 > 检测 > 修复,建立全方位缓存安防体系!