布隆过滤器

目录

    • 初识布隆过滤器
    • 使用布隆过滤器
    • 布隆过滤器如何实现
    • 布隆过滤器使用场景
    • 布隆过滤器存在问题
    • 解决策略

初识布隆过滤器

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

使用布隆过滤器

在Java中可以使用第三方库如Guava来实现布隆过滤器。

在guava包中的BloomFilter源码中,构造一个BloomFilter对象有四个参数:

  • Funnel funnel:数据类型,由Funnels类指定即可
  • long expectedInsertions:预期插入的值的数量
  • fpp:错误率
  • BloomFilter.Strategy:hash算法

使用Guava库实现布隆过滤器的示例代码如下:

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

public class BloomFilterExample {
    public static void main(String[] args) {
        // 创建布隆过滤器,设置预计插入的元素数量和误判率
        BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.unencodedCharsFunnel(), 1000, 0.01);

        // 添加元素到布隆过滤器
        bloomFilter.put("element1");
        bloomFilter.put("element2");

        // 判断元素是否存在于布隆过滤器中
        boolean exists = bloomFilter.mightContain("element1");
        System.out.println("Element exists: " + exists);
    }
}

布隆过滤器的预期误判率fpp是根据实际需求来设置的,一般情况下是根据对误判率的容忍度来确定的。误判率越低,布隆过滤器的空间和资源消耗也会增加。


布隆过滤器如何实现

BloomFilter 是由一个固定大小的二进制向量或者位图(bitmap)和一系列映射函数组成的,在初始状态时,相当于一个大型位数组,它的所有位都被置为0,

  • 插入元素,经过n个hash函数散列映射到位图中的n个点,并置为1
  • 查询元素,元素根据函数映射的n个点,检测n个点是否为1,有一个为0则证明元素不存在

所以可以判断元素一定不存在
判断某样东西一定不存在或者可能存在

原因在于,它通过多个hash函数进行散列,渐渐的数组上的1位越来越多,后续查询的元素映射的bit位也是1,一个bit位被多次映射为1,所以就不能判断这个元素是否存在

布隆过滤器的优点:

  • 时间复杂度低,增加和查询元素的时间复杂为O(N),(N为哈希函数的个数,通常情况比较小)
  • 保密性强,布隆过滤器不存储元素本身
  • 存储空间小,如果允许存在一定的误判,布隆过滤器是非常节省空间的(相比其他数据结构如Set集合)

布隆过滤器的缺点:

  • 有一定的误判率,但是可以通过调整参数来降低
  • 无法获取元素本身
  • 很难删除元素

布隆过滤器使用场景

缓存穿透

应对缓存穿透问题,我们可以使用布隆过滤器。
一个常见的缓存使用方式:读请求来了,先查下缓存,缓存有值命中,就直接返回;缓存没命中,就去查数据库,然后把数据库的值更新到缓存,再返回。
布隆过滤器_第1张图片


大量数据判断是否存在

这个中间层,是不是用HashMap就好了呢?HashMap时间复杂度可以达到O(1),但是因为HashMap数据是在内存里面的,如果大量的数据远超出了服务器的内存就无法使用HashMap,可以使用布隆过滤器来做这个缓冲,因为它只存储映射的位点
布隆过滤器_第2张图片


布隆过滤器存在问题

随着插入到位图的key越来越来,哈希碰撞频率也会越来越高,导致它有一定的误判率,可以用来判断元素一定不存在,但是不能保证元素一定存在

解决策略

  1. 调整布隆过滤器的参数:布隆过滤器的参数包括哈希函数的个数和位数组的大小。增加哈希函数的个数和位数组的大小可以降低误判率,但会增加存储空间和查询时间。根据应用场景的需求,可以根据误判率的可接受程度进行调整。
  2. 结合其他数据结构:可以将布隆过滤器与其他数据结构结合使用,以进一步降低误判率。例如,可以使用一个较小的布隆过滤器进行快速的初始过滤,然后对可能存在的元素进行进一步验证,例如使用一个哈希表或数据库进行准确的查询。
  3. 使用多个独立的布隆过滤器:使用多个独立的布隆过滤器,每个布隆过滤器使用不同的参数和哈希函数。当需要判断元素是否存在时,需要通过多个布隆过滤器的判断结果进行综合。这样可以降低误判率,但也会增加存储空间和查询时间。
  4. 添加计数器:在布隆过滤器的基础上,可以为每个哈希函数维护一个计数器,记录元素的出现次数。当判断元素存在时,可以检查所有哈希函数的计数器值,如果存在任一计数器值为0,则判断为误判。
  5. 定期重建布隆过滤器:定期重建布隆过滤器可以清除已经过时的元素,并减少误判率。定期重建的频率可以根据应用场景的需要进行调整。

你可能感兴趣的:(学习经验,#,Java基础,java,redis)