缓存穿透防护方案:布隆过滤器与空值缓存策略整合

Piper146 +0/-0 0 0 正常 2025-12-24T07:01:19 缓存一致性 · 布隆过滤器

缓存穿透防护方案:布隆过滤器与空值缓存策略整合

最近在优化后端服务的缓存一致性时,踩了一个大坑。项目中频繁出现缓存穿透问题,导致数据库压力过大。

问题复现步骤

  1. 高并发场景下,大量不存在的key请求直接打到数据库
  2. 数据库查询返回空结果,未做任何缓存处理
  3. 每次都走数据库查询,性能急剧下降

解决方案整合

我采用了布隆过滤器+空值缓存的双重防护策略:

// 布隆过滤器初始化
private final BloomFilter<String> bloomFilter = BloomFilter.create(
    Funnels.stringFunnel(Charset.defaultCharset()),
    1000000, // 预估容量
    0.01    // 误判率
);

// 缓存读取逻辑
public String getData(String key) {
    // 先用布隆过滤器检查是否存在
    if (!bloomFilter.mightContain(key)) {
        return null; // 直接返回,不查询数据库
    }
    
    String data = redisTemplate.opsForValue().get(key);
    if (data == null) {
        // 空值缓存处理
        data = queryFromDB(key);
        if (data == null) {
            // 缓存空值,避免缓存穿透
            redisTemplate.opsForValue().set(key, "", 5, TimeUnit.MINUTES);
        } else {
            // 正常缓存数据
            redisTemplate.opsForValue().set(key, data);
            // 同时加入布隆过滤器
            bloomFilter.put(key);
        }
    }
    return data;
}

实践总结

  • 布隆过滤器有效拦截99%以上的无效请求
  • 空值缓存避免了缓存击穿问题
  • 两种策略配合使用效果更佳,但要注意内存占用和维护成本
推广
广告位招租

讨论

0/2000
HighYara
HighYara · 2026-01-08T10:24:58
布隆过滤器确实能大幅降低无效查询,但别忘了它有误判率,建议结合业务场景控制在1%以内,并定期重建避免数据老化。
WeakAlice
WeakAlice · 2026-01-08T10:24:58
空值缓存是好招,但要设好过期时间,不然内存撑爆。我建议用随机过期+LRU淘汰机制,别让缓存变成数据垃圾场。