布隆过滤器

布隆过滤器是一种由位数组多个哈希函数组成概率数据结构,返回两种结果 可能存在 和 一定不存在

布隆过滤器里的一个元素由多个状态值共同确定。位数组存储状态值,哈希函数计算状态值的位置。

根据它的算法结构,有如下特征:

  • 使用有限位数组表示大于它长度的元素数量,因为一个位的状态值可以同时标识多个元素。
  • 不能删除元素。因为一个位的状态值可能同时标识着多个元素。
  • 添加元素永远不会失败。只是随着添加元素增多,误判率会上升。
  • 如果判断元素不存在,那么它一定不存在。

比如下面,X,Y,Z 分别由 3个状态值共同确定元素是否存在,状态值的位置通过3个哈希函数分别计算。

数学关系

误判概率

关于误判概率,因为每个位的状态值可能同时标识多个元素,所以它存在一定的误判概率。如果位数组满,当判断元素是否存在时,它会始终返回true,对于不存在的元素来说,它的误判率就是100%。

那么,误判概率和哪些因素有关,已添加元素的数量,布隆过滤器长度(位数组大小),哈希函数数量。

根据维基百科推理误判概率 PfpPfp 有如下关系:

Pfp=(1−[1−1m]kn)k≈(1−e−knm)kPfp=(1−[1−1m]kn)k≈(1−e−knm)k

  • mm 是位数组的大小;
  • nn 是已经添加元素的数量;
  • kk 是哈希函数数量;
  • ee 数学常数,约等于2.718281828。

由此可以得到,当添加元素数量为0时,误报率为0;当位数组全都为1时,误报率为100%。

不同数量哈希函数下,PfpPfp 和 nn 的关系如下图:

根据误判概率公式可以做一些事

  • 估算最佳布隆过滤器长度。
  • 估算最佳哈希函数数量。

最佳布隆过滤器长度

当 nn 添加元素和 PfpPfp误报概率确定时,mm 等于:

m=−nlnPfp(ln2)2≈−1.44⋅nlog2Pfpm=−nln⁡Pfp(ln⁡2)2≈−1.44⋅nlog2⁡Pfp

最佳哈希函数数量

当 nn 和 PfpPfp 确定时,kk 等于:

k=−lnPfpln2=−log2Pfpk=−ln⁡Pfpln⁡2=−log2⁡Pfp

当 nn 和 mm 确定时,kk 等于:

k=mnln2k=mnln⁡2

实现布隆过滤器

使用布隆过滤器前,我们一般会评估两个因素。

  • 预期添加元素的最大数量。
  • 业务对错误的容忍程度。比如1000个允许错一个,那么误判概率应该在千分之一内。

很多布隆过滤工具都提供了预期添加数量误判概率配置参数,它们会根据配置的参数计算出最佳的长度哈希函数数量

Java中有一些不错的布隆过滤工具包。

  • Guava 中 BloomFilter
  • redisson 中 RedissonBloomFilter 可以redis 中使用。

看下 Guava 中 BloomFilter 的简单实现,创建前先计算出位数组长度哈希函数数量

 static <T> BloomFilter<T> create(Funnel<? super T> funnel, long expectedInsertions, double fpp, Strategy strategy) {/*** expectedInsertions:预期添加数量* fpp:误判概率*/long numBits = optimalNumOfBits(expectedInsertions, fpp);int numHashFunctions = optimalNumOfHashFunctions(expectedInsertions, numBits);try {return new BloomFilter<T>(new BitArray(numBits), numHashFunctions, funnel, strategy);} catch (IllegalArgumentException e) {throw new IllegalArgumentException("Could not create BloomFilter of " + numBits + " bits", e);}}

根据最佳布隆过滤器长度公式,计算最佳位数组长度。


static long optimalNumOfBits(long n, double p) {if (p == 0) {p = Double.MIN_VALUE;}return (long) (-n * Math.log(p) / (Math.log(2) * Math.log(2)));}

根据最佳哈希函数数量公式,计算最佳哈希函数数量。

static int optimalNumOfHashFunctions(long n, long m) {return Math.max(1, (int) Math.round((double) m / n * Math.log(2)));}

redisson 中 RedissonBloomFilter 计算方法也是一致。

    private int optimalNumOfHashFunctions(long n, long m) {return Math.max(1, (int) Math.round((double) m / n * Math.log(2)));}private long optimalNumOfBits(long n, double p) {if (p == 0) {p = Double.MIN_VALUE;}return (long) (-n * Math.log(p) / (Math.log(2) * Math.log(2)));}

内存占用

设想一个手机号去重场景,每个手机号占用22 Byte,估算逻辑内存如下。

expected HashSet fpp=0.0001 fpp=0.0000001
100万 18.28MB 2.29MB 4MB
1000万 182.82MB 22.85MB 40MB
1亿 1.78G 228.53MB 400MB

注:实际物理内存占用大于逻辑内存。

误判概率 pp 和已添加的元素 nn,位数组长度 mm,哈希函数数量 kk 关系如下:

应用场景

  1. 弱密码检测;
  2. 垃圾邮件地址过滤。
  3. 浏览器检测钓鱼网站;
  4. 缓存穿透。

弱密码检测

维护一个哈希过弱密码列表。当用户注册或更新密码时,使用布隆过滤器检查新密码,检测到提示用户。

垃圾邮件地址过滤

维护一个哈希过垃圾邮件地址列表。当用户接收邮件,使用布隆过滤器检测,检测到标识为垃圾邮件。

浏览器检测钓鱼网站

使用布隆过滤器来查找钓鱼网站数据库中是否存在某个网站的 URL。

缓存穿透

缓存穿透是指查询一个根本不存在的数据,缓存层和数据库都不会命中。当缓存未命中时,查询数据库

  1. 数据库不命中,空结果不会写回缓存并返回空结果。
  2. 数据库命中,查询结果写回缓存并返回结果。

一个典型的攻击,模拟大量请求查询不存在的数据,所有请求落到数据库,造成数据库宕机。

其中一种解决方案,将存在的缓存放入布隆过滤器,在请求前进行校验过滤。

小结

对于千万亿级别的数据来说,使用布隆过滤器具有一定优势,另外根据业务场景合理评估预期添加数量误判概率是关键。

面试官问:什么是布隆过滤器?相关推荐

  1. 【200期】面试官问:Spring Security 和 Shiro 该如何选择?

    点击上方"Java精选",选择"设为星标" 别问别人为什么,多问自己凭什么! 下方有惊喜,留言必回,有问必答! 每天 08:15 更新文章,每天进步一点点... ...

  2. 面试官问你想找什么工作_找工作时如何面试面试官

    面试官问你想找什么工作 在技​​术面试中要问的十二个问题 (Twelve questions to ask at tech interviews) I've just come off six wee ...

  3. 面试官问:select......for update会锁表还是锁行?

    欢迎关注方志朋的博客,回复"666"获面试宝典 select查询语句是不会加锁的,但是select .......for update除了有查询的作用外,还会加锁呢,而且它是悲观锁 ...

  4. 面试官问:数据库 delete 表数据,磁盘空间还是被一直占用,为什么?

    以下文章来源方志朋的博客,回复"666"获面试宝典 最近有个上位机获取下位机上报数据的项目,由于上报频率比较频繁且数据量大,导致数据增长过快,磁盘占用多. 为了节约成本,定期进行数 ...

  5. 面试官问:Kafka 会不会丢消息?怎么处理的?

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! Kafka存在丢消息的问题,消息丢失会发生在Broker, ...

  6. 面试官问:Integer 如何实现节约内存和提升性能的?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:Byte_Liu 来源:https://urlify.cn/ ...

  7. 面试官问我:一个 TCP 连接可以发多少个 HTTP 请求?我竟然回答不上来...

    点击上方"方志朋",选择"设为星标" 做积极的人,而不是积极废人 作者 | 松若章 来源 | https://zhuanlan.zhihu.com/p/6142 ...

  8. 面试官问:请拿出一段体现你水平的代码,我该如何回答?

    程序员面试,免不了被问代码问题.如果面试官问你,最能代表你的当下水平的代码是什么?你该怎么回答呢?知乎的几位作者给出了优秀答案. 每天下班前半小时都会运行这段. #include <stdlib ...

  9. 后处理程序文件大小的变量_【每日一题】(17题)面试官问:JS中事件流,事件处理程序,事件对象的理解?...

    关注「松宝写代码」,精选好文,每日一题 作者:saucxs | songEagle 2020,实「鼠」不易 2021,「牛」转乾坤 风劲潮涌当扬帆,任重道远须奋蹄! 一.前言 2020.12.23 立 ...

  10. 当面试官问我ArrayList和LinkedList哪个更占空间时,我这么答让他眼前一亮

    前言 今天介绍一下Java的两个集合类,ArrayList和LinkedList,这两个集合的知识点几乎可以说面试必问的. 对于这两个集合类,相信大家都不陌生,ArrayList可以说是日常开发中用的 ...

最新文章

  1. windows监控——再见zmq
  2. [转]SVN + CruiseControl.NET + NANT 自动编译提交的项目最小DEMO
  3. PHP对二维数组中的某个字段的值进行排序
  4. 电中在线计算机应用基础二考试题目及答案,最新电大2015计算机应用基础作业2 答案.doc...
  5. 今天预计有多少人买饭团?李彦宏说百度用PaddlePaddle给答案
  6. Luogu P2595 [ZJOI2009]多米诺骨牌 容斥,枚举,插头dp,轮廓线dp
  7. Deep Learning 学习笔记
  8. VESA编程——GUI离我们并不遥远
  9. android 重力模拟,android的模拟器怎样仿真重力感应器
  10. 【Numpy】1. n维数组,dtype,切片,索引
  11. 综合评价之熵值法+TOPSIS
  12. 百度富文本编辑器使用方法 html,配置使用百度提供的富文本编辑器ueditor(以项目实例图文步骤演示具体配置步骤)...
  13. Ceph 学习——OSD读写流程与源码分析(一)
  14. Typec转HDMI 4K30HZ扩展芯片方案CS5261和CS5266设计参数及电路对比
  15. 12306.cn网站挂了”好文章收藏,引发的技术架构问题讨论。
  16. 尚学堂就业怎么样?谈谈我在尚学堂的就业之路
  17. 良好的客户服务始于帮助中心
  18. 基于SSM的文书处理及档案管理系统 java毕业设计
  19. Ubuntu下无法安装R语言vcd包解决办法
  20. Python基础教程-菜鸟教程学习笔记1

热门文章

  1. antiddos翻译_AntiDDoS8000系列DDoS防御系统
  2. 仪表指针样式_Qt自定义Widget之仪表盘
  3. Pandas 操作 csv 文件
  4. c++17(18)-static_cast
  5. 当深度学习遇上图: 图神经网络的兴起!(文末送书)
  6. 【机器学习基础】超全汇总!机器学习常用术语词汇表(建议收藏)
  7. 干货!华为AutoML助力AI开发效率提升攻略
  8. 斯坦福CS229机器学习课程的数学基础(线性代数)翻译完成
  9. 极致流畅体验的密码:网易云信 QoS 策略介绍 | 体验共享技术专题
  10. 娱乐社交,玩票大的!网易云信“2021融合通信开发者大赛”正式收官!