1. 先来认识缓存穿透的"犯罪现场"
假设我们运营一个日活百万的电商平台,某天突然发现数据库CPU飙升到90%。检查日志发现大量类似这样的请求:
SELECT * FROM products WHERE id = -123456789
这种明显不存在的数据请求绕过了Redis缓存层(因为缓存未命中),直接穿透到数据库,这就是典型的缓存穿透攻击场景。数据库每秒处理数千次无效查询,最终导致服务雪崩。
2. 防御武器库
武器一:布隆过滤器哨兵(Java+Redisson实现)
// 初始化布隆过滤器(Redisson客户端)
RBloomFilter<String> bloomFilter = redisson.getBloomFilter("productFilter");
// 预期数据量100万,误判率0.1%
bloomFilter.tryInit(1000000L, 0.001);
// 预热阶段:加载合法ID
for (Product product : productDao.findAll()) {
bloomFilter.add(product.getId());
}
// 查询拦截
public Product getProduct(String id) {
if (!bloomFilter.contains(id)) { // 布隆过滤器拦截
return null; // 直接拦截非法请求
}
// 后续正常查询逻辑...
}
优势:内存占用极低(百万数据仅需约1MB),拦截效率高
注意事项:需要定期同步数据库更新,误判率需根据业务调整
武器二:空值缓存战术(SpringBoot示例)
@Cacheable(value = "products", key = "#id",
unless = "#result == null") // 不缓存null值
public Product getProduct(String id) {
Product product = productDao.findById(id);
if (product == null) {
// 缓存空值(设置短过期时间)
redisTemplate.opsForValue().set("empty:"+id, "", 5, TimeUnit.MINUTES);
}
return product;
}
@Cacheable(value = "emptyProducts", key = "#id",
condition = "#id.startsWith('empty:')")
public String checkEmpty(String id) {
return null; // 直接返回空值缓存
}
适用场景:业务允许短暂空值显示的场合
注意事项:需预防恶意制造大量空键导致内存溢出
3. 实时监控作战室搭建
监控方案一:Redis慢查询分析
slowlog-log-slower-than 1000 # 记录超过1ms的查询
slowlog-max-len 1000 # 保留1000条记录
# 实时监控脚本
redis-cli slowlog get | grep 'get product:'
通过分析高频缓存取命令,识别异常访问模式
监控方案二:Prometheus+Granafa可视化
# prometheus.yml配置
scrape_configs:
- job_name: 'redis_exporter'
static_configs:
- targets: ['redis_exporter:9121']
监控指标包括:
- redis_missed_keys 统计缓存未命中率
- redis_hits_rate 缓存命中率
- command_call_count 命令调用排行
4. 进阶防御组合技
战术组合:布隆过滤器+本地缓存
// Caffeine本地缓存(Google Guava类似)
LoadingCache<String, Boolean> localCache = Caffeine.newBuilder()
.maximumSize(10_000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build(key -> bloomFilter.contains(key));
public boolean isValidId(String id) {
return localCache.get(id); // 双重缓存校验
}
优势:减少网络IO消耗,提升拦截速度
注意事项:需处理分布式环境的一致性同步问题
5. 应用场景分析
- 电商库存系统:秒杀场景中恶意刷不存在的商品ID
- 社交网络:遍历不存在的用户ID获取信息
- 物联网设备:伪造非法设备ID获取连接凭证
6. 技术选型对比表
方案 | 内存消耗 | 误判率 | 实现复杂度 | 适用场景 |
---|---|---|---|---|
布隆过滤器 | 低 | 0.1%-1% | 中 | 海量数据场景 |
空值缓存 | 中 | 无 | 低 | 数据离散场景 |
互斥锁 | 低 | 无 | 高 | 高并发更新场景 |
请求合并 | 低 | 无 | 高 | 热点数据场景 |
7. 防御体系构建原则
- 分层防御:在Nginx层做基础校验,应用层做逻辑校验,缓存层做最终防御
- 动态调整:根据监控数据自动调整布隆过滤器误判率
- 熔断机制:当数据库压力超过阈值时,自动开启验证码校验
8. 特别注意事项
- 热点Key处理:对类似-1、0等特殊值要做特殊过滤
- 缓存雪崩预防:空值缓存的TTL要设置随机值(如5分钟±随机30秒)
- 监控盲区:注意统计穿透请求的客户端特征(如相同IP、UA等)
9. 未来演进方向
- 机器学习防御:基于历史请求模式训练异常检测模型
- WebAssembly应用:在边缘节点实现高性能过滤逻辑
- 量子加密技术:防御基于量子计算的暴力破解攻击