【redis】布隆过滤器详解

简介

本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),它实际上是一个很长的二进制向量和一系列随机映射函数。

布隆过滤器可以用于检索一个元素是否在一个集合中,特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”,逻辑是当布隆过滤器说某个值存在时,这个值 可能不存在;当它说不存在时,那么 一定不存在。

优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。

适用场景

1.大数据判断是否存在

HashMap可以判断某个元素是否存,可以将值映射到 HashMap 的 Key,然后可以在 O(1) 的时间复杂度内返回结果,效率奇高。但是 HashMap 的实现也有缺点,例如存储容量占比高,考虑到负载因子的存在,通常空间是不能被用满的,而一旦你的值很多例如上亿的时候,那 HashMap 占据的内存大小就变得很可观了。这时候我们就需要考虑布隆过滤器了。

2.解决缓存穿透

什么是缓存穿透就不在这里解释了,在我之前的博客已经讲解过了。https://blog.youkuaiyun.com/wangyunzhao007/article/details/106478806

当有大量的请求访问我们不存在的数据中,缓存失效,会直接访问到数据库,当数据库扛不住压力时,数据库崩溃,这既是缓存穿透。而布隆过滤器可以判断访问的数据是否存在,当存在是才可以访问,不存在直接返回,避免了缓存穿透的发生。

数据结构和原理

布隆过滤器是一个 bit 向量或者说 bit 数组,长这样:

如果我们要映射一个值到布隆过滤器中,我们需要使用多个不同的哈希函数生成多个哈希值,并对每个生成的哈希值指向的 bit 位置 1

例如针对值 “hello” 和三个不同的哈希函数分别生成了哈希值 1、3、5,这把1,3,5对应的位改为1,则上图转变为:

再存一个值 “world”,如果哈希函数返回 3、4、8 ,我们把3,4,8对应的位改为1

接下来我们判断hello,world,haha,三个是否存在。根据上图的二进制向量图可以判断,三个哈希值对应的位都是1,则认为值存在,有一个零或者多个,则认为值不存在。

布隆过滤器认为当哈希值1,3,5对应的都是1,则认为world存在。

布隆过滤器认为当哈希值 3、4、8对应的都是1,则认为hello存在。

如果我们haha映射的值为3,4,5,布隆过滤器也认为haha存在,但其实是不存在,所以布隆过滤器会误判。

所以布隆过滤器说某个值存在时,这个值 可能不存在;当它说不存在时,那么 一定不存在。

缺点

  1. 随着数据的增加,误判率随之增加;
  2. 无法做到删除数据;
  3. 只能判断数据是否一定不存在,而无法判断数据是否一定存在。

guava实现布隆过滤器

引入pom

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

 代码

   private static int size = 1000000;//预计要插入多少数据

    private static double fpp = 0.01;//期望的误判率

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

    public static void main(String[] args) {
        //插入数据
        for (int i = 0; i < 1000000; i++) {
            bloomFilter.put(i);
        }
        int count = 0;
        for (int i = 1000000; i < 2000000; i++) {
            if (bloomFilter.mightContain(i)) {
                count++;
                System.out.println(i + "误判了");
            }
        }
        System.out.println("总共的误判数:" + count);
    }

代码简单分析:
我们定义了一个布隆过滤器,有两个重要的参数,分别是 我们预计要插入多少数据,我们所期望的误判率,误判率不能为0。
我向布隆过滤器插入了0-1000000,然后用1000000-2000000来测试误判率。

运行结果

 

用过判断了100万数据,一共误判10314,误判率10314/1000000=0.010314

和我们定义的期望误判率0.01相差无几

参考博客https://www.cnblogs.com/CodeBear/p/10911177.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值