布隆过滤器解决缓存穿透详解

1、什么是布隆过滤器

布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。

他就是一个很大的二进制数组

误判率跟哈希函数的次数,位数组的长度有关

 2、布隆过滤器原理

布隆过滤器的核心实现是一个超大的位数组和几个哈希函数。假设位数组的长度为m,哈希函数的个数为k

 3、空间计算

在布隆过滤器增加元素之前,首先需要初始化布隆过滤器的空间,也就是上面说的二进制数组,除此之外还需要计算无偏hash函数的个数。布隆过滤器提供了两个参数,分别是预计加入元素的大小n,运行的错误率f。布隆过滤器中有算法根据这两个参数会计算出二进制数组的大小l,以及无偏hash函数的个数k。

  • 错误率越低,位数组越长,控件占用较大
  • 错误率越低,无偏hash函数越多,计算耗时较长

4、测试一个元素是否属于一个百万元素集合所需耗时

4.1 引入依赖

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>22.0</version>
        </dependency>

4.2 测试

public class Test {
    private static int size = 1000000;

private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(),size);

    public static void main(String[] args) {
        for (int i = 0; i < size; i++) {
            bloomFilter.put(i);
        }

        ArrayList<Integer> list = new ArrayList<>(10000);
        for (int i = size+10000; i < size+20000; i++) {
            if (bloomFilter.mightContain(i)){
                list.add(i);
            }
        }
        System.out.println("误判的数量" + list.size());
    }
}

 从上面可以看出,我们故意取10000个不在过滤器里的值,却还有330个被认为在过滤器里,这说明误判率0.03

也可以该误判率,这就会导致位数增大

  

将所有可能存在的数据缓存放到布隆过滤器中,当黑客访问不存在的缓存时迅速返回避免缓存及DB挂掉。

redis伪代码如下所示

String get(String key) { //布隆过滤器钟存储的是数据库表钟对应的id
        if(!bloomfilter.mightContain(key)){
            return null;
        }
        String value=redis.get(key);//先从缓存获取.
        if(value!=null){
           return value;
        }
        value = db.get(key);//查询数据库
        redis.set(key, value);
        return value;
}

猜你喜欢

转载自blog.csdn.net/yhl15736773842/article/details/131554908