布隆过滤器的原理与使用

简介: 一、算法介绍 布隆过滤器是一种多哈希函数映射的快速查找算法,通常用于在大数据量场景下快速判断数据存在性。该算法通过牺牲正确性从而在空间和时间上都有不错的效率。 二、算法原理 当一个元素被加入集合时,通过N个散列函数将这个元素映射成一个位图中的N个点,将它们置为1。判断某个元素是否存在时,通过这些点是

布隆过滤器的原理与使用


一、算法介绍


布隆过滤器是一种多哈希函数映射的快速查找算法,通常用于在大数据量场景下快速判断数据存在性。该算法通过牺牲正确性从而在空间和时间上都有不错的效率。


二、算法原理


当一个元素被加入集合时,通过N个散列函数将这个元素映射成一个位图中的N个点,将它们置为1。判断某个元素是否存在时,通过这些点是不是都是1即可:如果这些点有任何一个0,则目标元素一定不在;如果都是1,则目标元素很可能在。例如,一个集合中只存在一个apple元素,其经过三个哈希函数计算映射在位图中三个位,此时判断orange是否存在于集合中,同样经过三个哈希函数计算,我们发现有一位为0,所以orange一定不存在于集合中。



三、算法实现


构造一个布隆过滤器需要一个给定长度的位图和N个哈希函数,那么问题来了,这个位图到底要多大?到底要多少个哈希函数呢?这里引入两个公式:


根据预估数据量n以及误判率fpp,位图大小m的计算方式:



根据预估数据量n以及位图长度m,哈希函数个数k的计算方式:


 

根据公式我们可以明显看出,当数据量越大、误判率越低,则位图长度越大。

关于m和k的计算,我们可以看一下Guava中的实现:


/**
     * 计算hash函数个数
     * n,预期数据量
     * m,位图长度
     */
    @VisibleForTesting
    static int optimalNumOfHashFunctions(long n, long m) {
        return Math.max(1, (int)Math.round((double)m / (double)n * Math.log(2.0D)));
    }
    /**
     * 计算位图长度
     * n,预估的数据量
     * p, 误判率
     */
    @VisibleForTesting
    static long optimalNumOfBits(long n, double p) {
        if (p == 0.0D) {
            p = 4.9E-324D;
        }
        return (long)((double)(-n) * Math.log(p) / (Math.log(2.0D) * Math.log(2.0D)));
    }


解决了位图长度和哈希函数个数的计算问题,接下来我们看看哈希函数选取问题,一般情况下我们都需要三个甚至更多的哈希函数,我们如果真要去准备这些函数那就太麻烦了,这里我们可以参考如下论文:


https://www.ccs.neu.edu/home/pete/pub/bloom-filters-verification.pdf


这篇论文提出了一种算法,把原本需要N个哈希函数的计算转化成了两个哈希值的运算,完美地解决了这个问题。如下所示:


 

上述公式中f(i)为第i个哈希函数。其中0 < i < k。也就是说使用a()和b()对一次输入求出两个不同的哈希值,然后将这两个哈希值代入此公式,便可求出N个哈希值。 在Guava中同样采用此算法,Guava的布隆过滤器中实现了MURMUR128_MITZ_32和MURMUR128_MITZ_64两种策略,我们以MURMUR128_MITZ_32为例看看:


public <T> boolean put(T object, Funnel<? super T> funnel, int numHashFunctions, BloomFilterStrategies.LockFreeBitArray bits) {
   long bitSize = bits.bitSize();
   long hash64 = Hashing.murmur3_128().hashObject(object, funnel).asLong();
   int hash1 = (int)hash64;
   int hash2 = (int)(hash64 >>> 32);
   boolean bitsChanged = false;
   for(int i = 1; i <= numHashFunctions; ++i) {
      int combinedHash = hash1 + i * hash2;
      if (combinedHash < 0) {
         combinedHash = ~combinedHash;
      }
      bitsChanged |= bits.set((long)combinedHash % bitSize);
   }
   return bitsChanged;
}


计算逻辑如下:


1)根据Murmur3算法计算出输入对象的64位哈希值,并将其分为两段,后32位为hash1,前32位为hash2,hash1对应公式中的函数a的返回值,hash2对应公式中的函数b的返回值;


2)将hash1、hash2和需要的哈希个数numHashFunctions代入公式中,逐个计算出每一个哈希值。


分类: 数据结构与算法

相关文章
|
4月前
|
存储 缓存 NoSQL
详解布隆过滤器原理与实现
详解布隆过滤器原理与实现
|
6月前
|
算法 容器
布隆过滤器
布隆过滤器
|
6月前
|
存储 机器学习/深度学习 缓存
【数据结构】布隆过滤器原理详解及其代码实现
【数据结构】布隆过滤器原理详解及其代码实现
|
7月前
|
算法 NoSQL Redis
一文搞懂布隆过滤器(BloomFilter)
一文搞懂布隆过滤器(BloomFilter)
433 0
|
7月前
|
存储 数据采集 缓存
解密布隆过滤器:数据领域的魔法阵
解密布隆过滤器:数据领域的魔法阵
118 0
|
存储 数据采集 缓存
布隆过滤器:原理与应用
在日常生活和工作中,我们经常需要处理海量的数据,筛选出有用的信息。这个时候,布隆过滤器(Bloom Filter)就派上了用场。
193 1
布隆过滤器:原理与应用
|
7月前
|
存储 NoSQL Java
什么是布隆过滤器?如何实现布隆过滤器?
什么是布隆过滤器?如何实现布隆过滤器?
137 0
从原理到实战:如何通过布隆过滤器防止缓存击穿
我们的业务中经常会遇到穿库的问题,通常可以通过缓存解决。如果数据维度比较多,结果数据集合比较大时,缓存的效果就不明显了。 因此为了解决穿库的问题,我们引入Bloom Filter。
|
存储 数据采集 自然语言处理
浅析布隆过滤器
布隆过滤器 (Bloom Filter) 是 1970 年由布隆提出的。它可以检索一个元素是否存在于集合中。它的优点是空间效率高,查询时间极快,缺点是有一定的误判率,而且删除困难。
176 0
|
索引
布隆过滤器的原理
布隆过滤器(Bloom Filter)是一种快速且高效的数据结构,用于判断一个元素是否存在于一个集合中。
191 0