布隆过滤器原理深度剖析
HBase布隆过滤器原理深度剖析
- 1. 数据结构与原理
- 1.1 初始化
- 1.2 变量映射
- 1.3 变量检索
- 1.4 总结
- 2. 过滤器特性
- 2.1 误判率
- 2.2 判断特点
- 3. 案列代码
1970年,布隆提出布隆过滤器(BloomFilter)
,用于判断一个元素是否不在一个集合中
,但是不能精确确定元素在集合中。
通常情况下,要确定一个元素是否存在于某个业务场景的集合,一般是将元素保存到集合中,然后通过比较确定,例如采用链表、树、散列表(又叫哈希表,Hash Table)等数据结构。但是,随着集合中元素的增加,需要的存储空间也会呈现线性增长,最终达到瓶颈,同时检索速度也越来越慢。因此,为了解决这种时间和空间性能问题,引入了布隆过滤器。
1. 数据结构与原理
BloomFilter是由一个固定大小的二进制向量
或者位图(Bitmap),和一系列映射函数组成。
1.1 初始化
初始状态时,需要指定位图(数组)长度(N),并将所有位都都置为0
。
上图所示,假设N=18
,则初始化Array=00 0000 0000 0000 0000
。
1.2 变量映射
布隆过滤器映射需要指定映射次数K,即变量需要映射到位图的K个点上,并将其位置值设置为1。
上图所示,假设位图长度N=18
,映射次数K=3
,哈希计算函数分别为hash1
,hash2
,hash3
。
那么,对于元素A={x, y, z}
加入布隆过滤器,则:
元素 | 第一次映射位置 | 第二次映射位置 | 第三次映射位置 |
---|---|---|---|
x | hash1(x) % N = 1 | hash2(x) % N = 5 | hash3(x) % N = 13 |
y | hash1(y) % N = 4 | hash2(y) % N = 11 | hash3(y) % N = 16 |
z | hash1(z) % N = 3 | hash2(z) % N = 5 | hash3(z) % N = 11 |
最终,得到布隆过滤器串为:01 0111 0000 0101 0010
1.3 变量检索
此时,元素w
加入,需要判断是否不存在。首先,经过K次映射计算其所在布隆过滤器位置。
元素 | 第一次映射位置 | 第二次映射位置 | 第三次映射位置 |
---|---|---|---|
w | hash1(x) % N = 4 | hash2(x) % N = 13 | hash3(x) % N = 15 |
其次,读取映射位置所在元素值,可以发现第三次映射位置
所在值为0,那么判定元素w
不存在于过滤器中。
1.4 总结
某个变量检索时,只要判断映射点值是否都为1,可以大概率判断是否存在于集合中。
- 如果映射点有任何一个0,则被检索变量一定不存在;
- 如果都是1,则被检索变量很可能存在。
思考:为什么说是可能存在,而不是一定存在呢?那是因为映射函数本身就是散列函数,散列函数是会有碰撞的。
2. 过滤器特性
2.1 误判率
布隆过滤器误判
:多个键经过映射后在相同bit位设置为1,导致无法判断究竟是哪个输入产生的,因此误判的根源在于相同bi 位被多次映射且设置为1。
这种情况也造成了布隆过滤器的删除存在问题,因为布隆过滤器每个bit并不是独占的,很有可能多个元素共享了某一位。如果我们直接删除这一位的话,会影响其他的元素。
2.2 判断特点
- 一个元素如果判断结果为存在的时候元素不一定存在,但是判断结果为不存在的时候则一定不存在。
- 布隆过滤器可以添加元素,但是不能删除元素。因为删掉元素会导致误判率增加。
3. 案列代码
package org.apache.ithink;/*** bloom filter* @author ithink/guojl.szu@hotmail.com* @date 2021-09-04*/
public class BloomFilter {/*** 映射次数*/private int k;/*** 每个Key占用字节数*/private int bitsPerKey;/*** 位图大小*/private int bitSize;/*** 底层存储位图*/private byte[] array;public BloomFilter(int k, int bitsPerKey) {this.k = k;this.bitsPerKey = bitsPerKey;}/*** 生成键值的位图* @param keys 键* @return 键对应位图*/public byte[] generate(String[] keys) {// 计算所有Key占用位数int actualBitSize = keys.length * bitsPerKey;// 由于每个字节占用8位// bitSize + 7 / 8: 避免bitSize < 8, 导致bitSize / 8为0// ((bitSize + 7) / 8) << 3: 保证位数是8的整数倍int middleBitSize = ((actualBitSize + 7) / 8) << 3; // Key最少占用64位int bitSize = middleBitSize < 64 ? 64 : middleBitSize;// 创建位图, 因为byte是8位, 所以需要将所有位数除以8array = new byte[bitSize >> 3];// 保存位图占用大小this.bitSize = bitSize;// 循环处理for (int i = 0; i < keys.length; i++) {// 生成Hash值int hashCode = Bytes.hash(keys[i].getBytes());// 循环映射K次for (int t = 0; t < k; t++) {// 计算所在位图位置// hashCode % bitSize + bitSize: 保证取模之后不为负数// (hashCode % bitSize + bitSize) % bitSize: 有可能括号内超过bitSize, // 所以需要再次取模计算int position = (hashCode % bitSize + bitSize) % bitSize;// 由于每个字节占用8位// position % 8: 计算位置所在当前字节第几位// (1 << (position % 8)): 将所在字节位值设置为1// position / 8: 计算position所在字节位置array[position / 8] |= (1 << (position % 8));// 将hashCode前17位和后15位进行位置切换int delta = (hashCode >> 17) | (hashCode << 15);// 保证每次计算的hashCode不同hashCode += delta;}}return array;}/*** 判断Key是否存在* @param key 键* @return true:存在, false:不存在*/public boolean contains(String key) {// 生成哈希值int hashCode = Bytes.hash(key.getBytes());// 循环映射K次for (int t = 0; t < k; t++) {// 计算所在位图位置int position = (hashCode % bitSize + bitSize) % bitSize;// 如果只要一个位置值为0, 则表示不存在if ((array[position / 8] & (1 << (position % 8))) == 0) {return false;}// 将hashCode前17位和后15位进行位置切换int delta = (hashCode >> 17) | (hashCode << 15);hashCode += delta;}return true;}
}
布隆过滤器原理深度剖析相关推荐
- git原理详解与实操指南_全网最精:学git一套就够了,从入门到原理深度剖析
以上资源收集至互联网 如有侵权请联系删除 资源获取方式 扫码关注资源库公众号 回复密码'20190812' 即可获得 截图展示 课程信息 课程难度:中级 学习人数:148352 课程状态:已完结 时长 ...
- 唯一插件化Replugin源码及原理深度剖析--插件的安装、加载原理
上一篇 唯一插件化Replugin源码及原理深度剖析–唯一Hook点原理 在Replugin的初始化过程中,我将他们分成了比较重要3个模块,整体框架的初始化.hook系统ClassLoader.插件的 ...
- 布隆过滤器原理和基于BloomFilter的误判率展示
布隆过滤器 布隆过滤器原理 布隆过滤器是由n个Hash函数和一个二进制数组组成. 如图所示(参考,hash函数可以多个) 1.保存操作 发来一个请求数据hello 对数据hello经过三次hash运算 ...
- 布隆过滤器误判怎么办为什么会_五分钟小知识:布隆过滤器原理和应用分析
布隆过滤器出现的背景和要解决的问题 Wikipedia 上面提到布隆过滤器早在 1970 年就被提出来,很难想象在当时那个年代它的主要用途是什么,估计当时提出也是一个数据模型吧. 在互联网时代,每天会 ...
- 云原生钻石课程 | 第6课:Kubernetes网络架构原理深度剖析(上)
点击上方"程序猿技术大咖",关注并选择"设为星标" 回复"加群"获取入群讨论资格! 本篇文章来自<华为云云原生王者之路训练营>钻 ...
- 【云驻共创】华为云云原生之Kubernetes网络架构原理深度剖析(上)
文章目录 前言 一.Kubernetes诞生背景 1.云原生的概念 2.云原生架构 3.Kubernetes(k8s) 二.Kubernetes基本网络模型剖析 1.概念厘清 1.1 二层桥接 VS ...
- 布隆过滤器原理和使用
LSM读放大问题背景 LSM树中读放大的来源是,我们必须寻址多个磁盘驻留表,以便完成读取操作.这是因为我们不一定能预先知道一个磁盘驻留表是否包含要搜索的键指向的数据记录. LSM使用bloomfilt ...
- 云原生钻石课程 | 第5课:Kubernetes存储架构原理深度剖析(下)
点击上方"程序猿技术大咖",关注并选择"设为星标" 回复"加群"获取入群讨论资格! 本篇文章来自<华为云云原生王者之路训练营>钻 ...
- Mysql binlog应用场景与原理深度剖析
1 基于binlog的主从复制 Mysql 5.0以后,支持通过binary log(二进制日志)以支持主从复制.复制允许将来自一个MySQL数据库服务器(master) 的数据复制到一个或多个其他M ...
最新文章
- hdu 4101(bfs+博弈)
- 牛客题霸 NC14 按之字形顺序打印二叉树
- 怎么把PPT变成word文档
- 计算图片的宽和高 动态设置图片的位置
- 03.JavaScript对DOM操作
- 不同于NLP,数据驱动、机器学习无法攻克NLU,原因有三
- python封装介绍_谈python3的封装
- 研究大学生基础课程成绩和专业课程成绩的关系,证明两者之间是否有线性关系
- 一张图了解互联网产品盈利模式
- 二级c语言题库分类,二级C语言题库分类.xls
- Amazon Alexa Smart Home Skill 增加订阅事件
- 安卓开发基础知识4(三星 、ARM 为大朋背书,详解VR一体机解决方案)
- 两级运放积分器的带宽分析
- 计算机中键盘可以共享吗,步骤详解什么是双模键盘(两台电脑共用一套鼠标键盘)...
- Qt编写邮件客户端IMAP4(一)收取邮件
- PHP事务数据库写法,PHP 操作 MySQL 执行数据库事务
- RSA的dp泄露 —— 【WUST-CTF2020】leak
- cocos2d-x ui::Button 的setEnabled 和 setVisible 的区别,setEnabled后按钮却不见了
- linux下批量创建文件(空文件、带内容文件)、文件夹
- Python爬虫-爬取常用IP代理
热门文章
- C# word中添加横线
- 重点人员动态管控系统开发,智慧公安合成作战平台搭建
- tarjan+拓扑序+差分--2018.10.16模拟赛T2
- linux 下缓存失败,Linux下搭建网站提示缓存文件写入失败怎么办?
- python 编写端口扫描器
- html背景纹理,如何用css3制作纹理背景
- C语言在线运行,编辑
- 小程序接入h5页面_小程序-实现怎么跳转打开 H5 网页链接(或跳转至公众号文章)...
- 毕设:基于SpringBoot+Vue 实现在线考试系统(前后端分离)
- AJAX框架衣柜推拉门设计,自己diy动手四推拉门衣柜内部结构设计图纸