布隆过滤器 Bloom Filter

  什么是布隆过滤器:  

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

  布隆过滤器的实现原理:

  举例说明,假如现在有10个单词,可以创建100bit的数组,然后分别对每个单词采用5个Hash函数进行运算后得到5个Hash值,将这5个值对应的数组的位置置为1。判端下一个单词是否存在于这10个单词中的时候,只要查看这个单词hash后对应的5个位置是否都是1,如果有一个位置不是1,说明这个单词一定不存在与之前10个单词之中,如果全是1,说明这个单词可能存在那10个单词当中。

   

  由此可知,布隆过滤器只能进行插入和是否存在操作,不能进行删除操作。布隆过滤器存在一定的误判,只能保证一定不存在,但不能保证一定存在。如何减少误判率,核心思想就是减少指针碰撞,主要通过增加hash的个数和扩大bit数组的长度来减少指针碰撞的概率。

  布隆过滤器的java代码应用:

  pom.xml

<dependency>
    <groupId>com.github.alexandrnikitin</groupId>
    <artifactId>bloom-filter_2.12</artifactId>
    <version>0.11.0</version>
</dependency>

  具体代码示例

@RunWith(SpringRunner.class)
@SpringBootTest
public class BloomFilterTest {
    private BloomFilter<Integer> bloomFilter;

    private int size = 1000000;
    @Before
    public void init(){
        //不设置第三个参数时,误判率默认为0.03
        //bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size);
        //进行误判率的设置,自动计算需要几个hash函数。bit数组的长度与size和fpp参数有关
        //过滤器内部会对size进行处理,保证size为2的n次幂。
        bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, 0.01);
        for(int i = 0; i < size; i++){
            bloomFilter.put(i);
        }
    }
    @Test
    public void testBloomFilter(){
        for(int i = 0; i < size; i++){
            if(!bloomFilter.mightContain(i)){
                //不会打印,因为不存在的情况不会出现误判
                System.out.println("不存在的误判" + i);
            }
        }

        List<Integer> list = new ArrayList<>(1000);
        for (int i = size + 10000; i < size + 20000; i++) {
            if (bloomFilter.mightContain(i)) {
                list.add(i);
            }
        }
        //根据设置的误判率
        System.out.println("存在的误判数量:" + list.size());
    }
}

 

  布隆过滤器有以下应用场景:

  1、黑名单,比如邮件黑名单过滤器,判端邮件地址是否在黑名单中。

  2、网络爬虫,判端url是否已经被爬取过。

  3、首次访问,判端访问网站的IP是否是第一次访问。

  4、缓存击穿,防止非法攻击,频繁发送无法命中缓存的请求,导致缓存击穿,最总引起缓存雪崩。

  5、检查英文单词是否拼写正确。

  6、K-V系统快速判断某个key是否存在,典型的例子有Hbase,Hbase的每个Region中都包含一个BloomFilter,用于在查询时快速判断某个key在该region中是否存在,如果不存在,直接返回,节省掉后续的查询。

  扩展,如何让布隆过滤器支持删除。

  进行计数删除,但是计数删除需要存储一个数值,而不是原先的 bit 位,会增大占用的内存大小。这样的话,增加一个值就是将对应索引槽上存储的值加一,删除则是减一,判断是否存在则是看值是否大于0。

posted @ 2019-03-13 15:53  长途跋涉的孤狼  阅读(380)  评论(0编辑  收藏  举报