Redis缓存穿透

缓存穿透:在这种情况下,缓存服务器找不到指定key的有效缓存信息,同时下游的数据库也查询不到对应的数据,这就造成了业务系统的无效请求全部落在了数据库上,缓存服务器完全没有起到作用。

解决方案:
1)缓存空数据,查询返回的数据为空,仍把这个结果进行缓存

优点:简单

缺点:消耗内存,可能发生不一致问题

2)布隆过滤器

优点:内存占用较少,没有多余key

缺点:实现复杂,存在误判

布隆过滤器是一种数据结构,用于快速检索一个元素是否可能存在于一个集合(bit数组)中。

它的基本原理是利用多个哈希函数,将一个元素映射成多个位,然后将这些位设置成1。当查询一个元素时,如果这些位都被设置成1,则认为元素可能存在于集合中,否则肯定不存在。

所以,布隆过滤器可以准确判断一个元素是否肯定不存在,但是因为hash冲突的原因,所以它没办法判断一个元素是否一定存在。只能判断可能存在。

误判率:如果判断元素存在,可能存在误判。跟数组长度有关,数组长度越长,误判率越低,但是内存消耗增大。数组长度越小,误判率越高,内存消耗越低。一般保证误判率在5%以内可以没满足需要。

流程:

使用步骤:

Java中可以使用第三方库来实现布隆过滤器,常见的有Google Guava库和Apache Commons库以及Redis

Guava

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;

public class BloomFilterExample {
    public static void main(String[] args) {
        // 创建布隆过滤器,预计插入100个元素,误判率为0.01
        BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringsFunctor(), 10, 0.01); 

        // 插入元素
        bloomFilter.put("Hollis");
        bloomFilter.put("666");
        bloomFilter.put("八股文");

        // 判断元素是否存在
        System.out.println(bloomFilter.mightContain("Hollis"));   // true
        System.out.println(bloomFilter.mightContain("王星星"));  // false
    }
}

Apache Commons

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.collections4.BloomFilter;
import org.apache.commons.collections4.functors.HashTransformer;

public class BloomFilterExample {

    public static void main(String[] args) {
        // 创建布隆过滤器,预测插入100个元素,误判率为0.01
        BloomFilter<String> bloomFilter = new BloomFilter<>(HashFunctionIdentity.hashFunction(String::hashCode), 100, 0.01);

        bloomFilter.put("Hollis");
        bloomFilter.put("666");
        bloomFilter.put("八股文");

        // 判断元素是否存在
        System.out.println(bloomFilter.mightContain("Hollis"));   // true
        System.out.println(bloomFilter.mightContain("王星星"));  // falses

        // 清除所有已知条目
        for (String key : bloomFilter.keys()) {
            bloomFilter.remove(key);
        }
    }
}
3) Redis中可以通过Bloom模块来使用,使用Redisson可以:
//创建 Config 对象,设置单个服务器地址
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379/");
//创建 RedissonClient 对象
RedissonClient redisson = Redisson.create(config);
//获取 RBloomFilter 对象
RBloomFilter<String> bloomFilter = redisson.getBlobStore("myfilter").getOrInit(new StringSerializer<>());
//初始化布隆过滤器,参数分别为容量(max elements)和误识别率(false positive rate)
bloomFilter.tryInit(100, 0.01);

bloomFilter.add("Hollis");
bloomFilter.add("666");
bloomFilter.add("八股文");

System.out.println(bloomFilter.contains("Hollis"));
System.out.println(bloomFilter.contains("王巨星"));

//关闭客户端
redisson.shutdown();

或者Jedis

Jedis jedis = new Jedis("localhost");

jedis.bfCreate("myfilter", 100, 0.01);

jedis.bfAdd("myfilter", "Hollis");
jedis.bfAdd("myfilter", "666");
jedis.bfAdd("myfilter", "八股文");

System.out.println(jedis.bfExists("myfilter", "Hollis"));
System.out.println(jedis.bfExists("myfilter", "王星星"));

jedis.close();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值