面试官连环追问:Redis缓存穿透的7种解决方案,你敢说全吗?

导读:在电商大促期间,某平台因缓存穿透导致数据库崩溃,直接损失超千万。本文通过复现事故场景,剖析7种缓存穿透解决方案的底层原理。无论面试还是实战,这篇文章都将成为你的终极防穿透指南。


一、穿透场景复现与问题诊断

1.1 高并发穿透场景模拟

// 危险代码示例:未做防护的查询方法
public Product getProduct(String id) {
   
    String cacheKey = "product:" + id;
    Product product = redisTemplate.opsForValue().get(cacheKey);
    if (product != null) {
   
        return product;
    }
    
    product = productMapper.selectById(id); // 直接查库
    if (product != null) {
   
        redisTemplate.opsForValue().set(cacheKey, product, 30, TimeUnit.MINUTES);
    }
    return product;
}

漏洞分析:恶意攻击者通过构造随机ID(如UUID)发起海量查询,所有请求穿透Redis直达MySQL。当QPS达到2万时,数据库连接池瞬间耗尽。


二、7大解决方案深度解析

2.1 布隆过滤器(Bloom Filter)

// 初始化布隆过滤器(Redisson实现)
RBloomFilter<String> bloomFilter = redisson.getBloomFilter("product_filter");
bloomFilter.tryInit(1000000L, 0.01); // 百万数据量,1%误判率

// 查询时优先校验
public Product getProductWithBloom(String id) {
   
    if (!bloomFilter.contains(id)) {
   
        return null; // 快速拦截非法请求
    }
    // ...原有查询逻辑
}

核心参数

  • 位数组大小:-n*ln(p)/(ln2)^2 (n=元素数量,p=误判率)
  • 哈希函数数量:k = m/n * ln2

2.2 缓存空对象(Cache Null)

public Product getProductWithNullCache(String id) {
   
    String cacheKey = "product:" + id;
    Product product = redisTemplate.opsForValue().get(cacheKey);
    
    if (product != null) {
   
        return product instanceof NullProduct ? null : product;
    }
    
    product = productMapper.selectById(id);
    if (product != null) {
   
        redisTemplate.opsForValue().set(cacheKey, product, 30, TimeUnit.MINUTES);
    } else {
   
        redisTemplate.opsForValue().set(cacheKey, new NullProduct(), 2, TimeUnit.MINUTES); // 短时间缓存空值
    }
    return product;
}

注意事项

<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值