介绍

布隆过滤器在wiki上的介绍:

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

为什么要用布隆过滤器?

事实上,布隆过滤器被广泛用于网页黑名单系统、垃圾邮件过滤系统、爬虫的网址判重系统以及解决缓存穿透问题。通过介绍已经知晓布隆过滤器的作用是检索一个元素是否在集合中。可能有人认为这个功能非常简单,直接放在redis中或者数据库中查询就好了。又或者当数据量较小,内存又足够大时,使用hashMap或者hashSet等结构就好了。但是如果当这些数据量很大,数十亿甚至更多,内存装不下且数据库检索又极慢的情况,我们应该如何去处理?这个时候我们不妨考虑下布隆过滤器,因为它是一个空间效率占用极少和查询时间极快的算法,但是需要业务可以忍受一个判断失误率。

哈希函数

布隆过滤器离不开哈希函数,所以在这里有必要介绍下哈希函数的概念,如果你已经掌握了,可以直接跳到下一小节。

哈希函数的性质:

经典的哈希函数都有无限大的输入值域(无穷大)。

经典的哈希函数的输出域都是固定的范围(有穷大,假设输出域为S)

当给哈希函数传入相同的值时,返回值必一样

当给哈希函数传入不同的输入值时,返回值可能一样,也可能不一样。

输入值会尽可能均匀的分布在S上

前三点都是哈希函数的基础,第四点描述了哈希函数存在哈希碰撞的现象,因为输入域无限大,输出域有穷大,这是必然的,输入域中会有不同的值对应到输入域S中。第五点事评价一个哈希函数优劣的关键,哈希函数越优秀,分布就越均匀且与输入值出现的规律无关。比如存在"hash1","hash2","hash3"三个输入值比较类似,经过哈希函数计算后的结果应该相差非常大,可以通过常见的MD5和SHA1算法来验证这些特性。如果一个优秀的函数能够做到不同的输入值所得到的返回值可以均匀的分布在S中,将其返回值对m取余(%m),得到的返回值可以认为也会均匀的分布在0~m-1位置上。

基于缓存业务分析布隆过滤器原理

在大多应用中,当业务系统中发送一个请求时,会先从缓存中查询;若缓存中存在,则直接返回;若返回中不存在,则查询数据库。其流程如下图所示:

缓存穿透:当请求数据库中不存在的数据,这时候所有的请求都会打到数据库上,这种情况就是缓存穿透。如果当请求较多的话,这将会严重浪费数据库资源甚至导致数据库假死。

接下来开始介绍布隆过滤器。有一个长度为m的bit型数组,如我们所知,每个位置只占一个bit,每个位置只有0和1两种状态。假设一共有k个哈希函数相互独立,输入域都为s且都大于等于m,那么对同一个输入对象(可以想象为缓存中的一个key),经过k个哈希函数计算出来的结果也都是独立的。对算出来的每一个结果都对m取余,然后在bit数组上把相应的位置设置为1(描黑),如下图所示:

至此一个输入对象对bit array集合的影响过程就结束了,我们可以看到会有多个位置被描黑,也就是设置为1.接下来所有的输入对象都按照这种方式去描黑数组,最终一个布隆过滤器就生成了,它代表了所有输入对象组成的集合。

那么如何判断一个对象是否在过滤器中呢?假设一个输入对象为hash1,我们需要通过看k个哈希函数算出k个值,然后把k个值取余(%m),就得到了k个[0,m-1]的值。然后我们判断bit array上这k个值是否都为黑,如果有一个不为黑,那么肯定hash1肯定不在这个集合里。如果都为黑,则说明hash1在集合里,但有可能误判。因为当输入对象过多,而集合过小,会导致集合中大多位置都会被描黑,那么在检查hash1时,有可能hash1对应的k个位置正好被描黑了,然后错误的认为hash1存在集合里。

控制布隆过滤器的误判率

如果bit array集合的大小m相比于输入对象的个数过小,失误率就会变高。这里直接引入一个已经得到证明的公式,根据输入对象数量n和我们想要达到的误判率为p计算出布隆过滤器的大小m和哈希函数的个数k.

布隆过滤器的大小m公式:

哈希函数的个数k公式:

布隆过滤器真实失误率p公式:

假设我们的缓存系统,key为userId,value为user。如果我们有10亿个用户,规定失误率不能超过0.01%,通过计算器计算可得m=19.17n,向上取整为20n,也就是需要200亿个bit,换算之后所需内存大小就是2.3G。通过第二个公式可计算出所需哈希函数k=14.因为在计算m的时候用了向上取整,所以真是的误判率绝对小于等于0.01%。

快速集成BloomFilter

关于布隆过滤器,我们不需要自己实现,谷歌已经帮我们实现好了。

pom引入依赖

com.google.guava

guava

25.1-jre

核心api

/**

* Creates a {@link BloomFilter BloomFilter} with the expected number of

* insertions and expected false positive probability.

*

*

Note that overflowing a {@code BloomFilter} with significantly more elements

* than specified, will result in its saturation, and a sharp deterioration of its

* false positive probability.

*

*

The constructed {@code BloomFilter} will be serializable if the provided

* {@code Funnel} is.

*

*

It is recommended that the funnel be implemented as a Java enum. This has the

* benefit of ensuring proper serialization and deserialization, which is important

* since {@link #equals} also relies on object identity of funnels.

*

* @param funnel the funnel of T's that the constructed {@code BloomFilter} will use

* @param expectedInsertions the number of expected insertions to the constructed

* {@code BloomFilter}; must be positive

* @param fpp the desired false positive probability (must be positive and less than 1.0)

* @return a {@code BloomFilter}

*/

public static BloomFilter create(

Funnel funnel, int expectedInsertions /* n */, double fpp) {

checkNotNull(funnel);

checkArgument(expectedInsertions >= 0, "Expected insertions (%s) must be >= 0",

expectedInsertions);

checkArgument(fpp > 0.0, "False positive probability (%s) must be > 0.0", fpp);

checkArgument(fpp < 1.0, "False positive probability (%s) must be < 1.0", fpp);

if (expectedInsertions == 0) {

expectedInsertions = 1;

}

/*

* TODO(user): Put a warning in the javadoc about tiny fpp values,

* since the resulting size is proportional to -log(p), but there is not

* much of a point after all, e.g. optimalM(1000, 0.0000000000000001) = 76680

* which is less than 10kb. Who cares!

*/

long numBits = optimalNumOfBits(expectedInsertions, fpp);

int numHashFunctions = optimalNumOfHashFunctions(expectedInsertions, numBits);

try {

return new BloomFilter(new BitArray(numBits), numHashFunctions, funnel,

BloomFilterStrategies.MURMUR128_MITZ_32);

} catch (IllegalArgumentException e) {

throw new IllegalArgumentException("Could not create BloomFilter of " + numBits + " bits", e);

}

}

/**

* Returns {@code true} if the element might have been put in this Bloom filter,

* {@code false} if this is definitely not the case.

*/

public boolean mightContain(T object) {

return strategy.mightContain(object, funnel, numHashFunctions, bits);

}

一个小例子

public static void main(String... args){

/**

* 创建一个插入对象为一亿,误报率为0.01%的布隆过滤器

*/

BloomFilter bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.forName("utf-8")), 100000000, 0.0001);

bloomFilter.put("121");

bloomFilter.put("122");

bloomFilter.put("123");

System.out.println(bloomFilter.mightContain("121"));

}

布隆过滤器误判怎么办为什么会_说一说布隆过滤器相关推荐

  1. 布隆过滤器误判怎么办为什么会_五分钟小知识:布隆过滤器原理和应用分析

    布隆过滤器出现的背景和要解决的问题 Wikipedia 上面提到布隆过滤器早在 1970 年就被提出来,很难想象在当时那个年代它的主要用途是什么,估计当时提出也是一个数据模型吧. 在互联网时代,每天会 ...

  2. 布隆过滤器误判_布隆过滤器原理

    布隆过滤器 布隆过滤器拥有极高的性能,无论是写入操作还是读取操作,时间复杂度是O(1). 在空间上相对于其他数据结构,有很大优势, 20亿的数据需要 2000000000bit/8/1024/1024 ...

  3. mysql开启布隆过滤器_海量数据去重之布隆过滤器

    背景 在使⽤word⽂档时,word如何判断某个单词是否拼写正确? ⽹络爬⾍程序,怎么让它不去爬相同的url⻚⾯? 垃圾邮件(短信)过滤算法如何设计? 公安办案时,如何判断某嫌疑⼈是否在⽹逃名单中? ...

  4. 过滤设置_深圳外置鱼池过滤器零售_杰蒙尼鱼池过滤器

    首页 > 新闻中心 发布时间:2021-01-08 03:54:45 导读:杰蒙尼鱼池过滤器为您提供深圳外置鱼池过滤器零售的相关知识与详情: 自清洗过滤器这一废水再利用,符合当今倡导了循环经济, ...

  5. 流放之路材质过滤怎么设置_房子装修,前置过滤器怎么选?看这6个要点

    我们平时家里用的自来水,其实是需要过滤的,因为自来水在出厂前,水是很干净的,但是经过漫长的水管或小区储水池,运输到家里的水可能有铁锈.泥沙.大颗粒悬浮物等杂质,所以家里的总入水管处是很有必要装一个前置 ...

  6. springboot过滤器排除掉一些url_理解这9大内置过滤器,才算是精通Shiro

    小Hub领读: 权限框架一般都是一堆过滤器.拦截器的组合运用,在shiro中,有多少个内置的过滤器你知道吗?在哪些场景用那些过滤器,这篇文章希望你能对shiro有个新的认识! 别忘了,点个 [在看] ...

  7. Filter过滤器和动态代理处理机制和案例(Filter过滤器和动态代理结合)

    关注公众号:"奇叔码技术" 回复:"java面试题大全"或者"java面试题" 即可免费领取资料 Filter过滤器和动态代理处理机制和案例 ...

  8. mysql布隆过滤器源码_通过实例解析布隆过滤器工作原理及实例

    布隆过滤器 布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地插入和查询,可以用来告诉你 "一定不存在或者可能存在& ...

  9. java面包屑实现_在Java中实现过滤器和面包店锁

    java面包屑实现 为了了解锁的工作原理,实现自定义锁是一种好方法. 这篇文章将展示如何在Java上实现Filter和Bakery锁(自旋锁),并将它们的性能与Java的ReentrantLock进行 ...

最新文章

  1. 设计模式之工厂类模式总结对比、简单工厂模式、工厂方法模式、抽象工厂模式、带反射的工厂模式、例子代码分析、最详细
  2. 年终盘点:2015年人工智能的五大关键词
  3. 批量kill掉linux中符合某些字段的进程
  4. 从生活角度学习应用程序、虚拟目录、应用程序池(解惑篇)
  5. ospf 环回口的路由条目_华为OSPF基础实验
  6. python 多线程读写文件_Python多线程同步---文件读写控制方法
  7. 微信公众号中视频下载的2种方法
  8. win10计算机护眼,win10系统开启电脑护眼的操作方法
  9. 基于英雄联盟寻路背景的A星算法及python实现
  10. fusion 360动态观察的快捷键
  11. VirtualBox虚拟机全屏显示
  12. 降维打击 Dimensionality reduction attack
  13. html标签的message,Message 消息提示
  14. Linux局域网共享打印机(实用型文档)
  15. webpack 的安装与使用
  16. 简单C程序示例及分析
  17. 宏碁星锐4750的安装驱动步骤
  18. 用3D再现2D偶像的可爱,Cygames【偶像大师 灰姑娘女孩】开发示例
  19. 未能加载文件或程序集“Newtonsoft.Json, Version=4.5.0.0, Culture=neutral
  20. 小巧实用的pdf阅读器

热门文章

  1. 弘辽科技:拼多多新店选什么推广方式?
  2. 互点流量,互刷排名,刷下拉刷联想-胖虎图图-互动点击系统
  3. Android中动画类别及优缺点,安卓培训学习:注册广播及其优缺点
  4. 一个数据分析师,在公司里的主要职责是什么?
  5. linux下限制每个IP网速
  6. 基于 Amazon Amplify 构建自己的首个 iOS 应用程序(二)
  7. agv ti 毫米波雷达_一种基于毫米波雷达的AGV小车的制作方法
  8. Hangzhou Invitation Day1
  9. 细胞培养常见问题分析
  10. 《算法图解》学习笔记(十一):十种经典的算法与数据结构