原理
布隆过滤器(Bloom Filter)是一种数据结构,由布隆于1970年提出。它由一个很长的二进制向量和一系列随机映射函数组成。其主要应用是判断一个元素是否在一个集合中。布隆过滤器具有空间效率和查询时间远远超过一般算法的优点,但也存在一定的误判率和删除困难的缺点。
Bloom Filter的原理
在元素加入集合时,通过多个散列函数将元素映射到位数组中的多个点,并将它们置为1。在检索时,只需检查这些点是否都为1,就可以(大致)确定集合中是否存在该元素:如果其中有任何一个点为0,则被检元素一定不存在;如果都为1,则被检元素很可能存在。这是布隆过滤器的基本思想。
与单一哈希函数和位图不同,布隆过滤器使用了多个哈希函数,每个元素与多个位对应,以降低冲突的概率。
举个例子,我们首先将数据库中的数据加载到布隆过滤器中,比如数据库的ID有:1、2、3。下次查询时,如果查询的ID也是1,我们就对1进行三次哈希运算,看看与之前的三个位置是否完全一致,如果一致,就可以确定过滤器中存在1,反之则说明不存在。
Bloom Filter的缺点
bloom filter之所以能做到在时间和空间上的效率比较高,是因为牺牲了判断的准确率、删除的便利性
1、存在误判。在判断元素是否存在时,有可能将其他元素设置的bit位加入计算,导致未存在在容器中的元素被认为已经存在。
2、删除困难。如果在删除元素时贸然将对应bit位置为0,会导致其他映射到此bit位数据的查找失效。
Bloom Filter 实现
在Guava中提供了一种Bloom Filter的实现。
在Guava库中,Bloom Filter的实现位于com.google.common.hash包下的BloomFilter类中。
在使用Bloom Filter 我们需要首先确定hash函数及预期插入数量,还有期望误判率
代码语言:javascript复制// BloomFilter 的创建BloomFilter<T> bloomFilter = BloomFilter.create(hashFunction, expectedInsertions, falsePositiveProbability);
// 存放值bloomFilter.put(element)
//判断BloomFilter 是否存在对应元素boolean exists = bloomFilter.mightContain(element);
此处的hashFunction也可以使用Guava库中的`HashFunction`工具类来创建。
Guava的Bloom Filter实现还提供了其他一些方法和功能,例如批量插入元素、序列化和反序列化等。可以根据具体需求使用相应的方法。
常见的应用场景
缓存系统: 布隆过滤器可用于缓存系统中,以快速判断一个数据是否已经存在于缓存中。例如,在网页缓存中,当一个用户请求一个网页时,可以首先使用布隆过滤器判断该网页是否已经被缓存,如果不存在则从后端获取并缓存,避免了不必要的数据库查询或网络请求。
数据库查询优化:在数据库查询中,可以使用布隆过滤器来快速判断一个元素是否存在于数据库中,从而避免执行昂贵的数据库查询操作。可以将热门查询结果的主键构建成布隆过滤器,当一个查询请求来临时,首先通过布隆过滤器判断该主键是否可能存在于数据库中,如果不存在则可以避免执行查询操作,从而提高查询效率。
防止缓存穿透:布隆过滤器可以用于防止缓存穿透,即当一个查询请求的结果不在缓存中时,为了避免频繁查询数据库,可以首先通过布隆过滤器判断该请求是否为无效请求,如果是无效请求,则可以直接返回空结果,从而减轻对数据库的压力。
垃圾邮件过滤:布隆过滤器可用于垃圾邮件过滤系统,以快速判断一封邮件是否为垃圾邮件。将已知的垃圾邮件特征构建成布隆过滤器,当一封新的邮件到达时,可以通过布隆过滤器判断该邮件是否可能为垃圾邮件,从而提高垃圾邮件过滤的效率。
URL去重:在网络爬虫等应用中,需要对已经访问过的URL进行去重操作,以避免重复爬取相同的网页。布隆过滤器可以用于快速判断一个URL是否已经被访问过,从而避免重复工作。
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!