06——布隆过滤器BloomFilter
一、是什么
由一个初始值都为零的bit数组和多个哈希函数构成,用来快速判断集合中是否存在某个元素
设计思想:
1. 目的:减少内存占用
1. 方式:不保存数据信息,只是在内存中做一个是否存在的标记flag
1. 本质:判断具体数据是否在一个大的集合中
备注:布隆过滤器时一种类似set的数据结构,只是统计结果在巨量数据下有 小瑕疵,不够完美
二、能干嘛
- 高效地插入和查询,占用空间少,返回的结果是不确定性+不够完美(哈希冲突)。
- 重点:一个元素如果判断结果:存在时,元素不一定存在,但是判断结果不存在时,则一定不存在。
- 布隆过滤器可以添加元素,但是不能删除元素,由于涉及hascode判断依据,删除元素会导致误判率增加。
- 总结:
- 有:可能有
- 无:一定无
三、原理
-
布隆过滤器实现原理和数据结构
添加key与查询key
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e1B6gZyW-1692427541189)(https://you-blog.oss-accelerate.aliyuncs.com/2023/202303132220955.png)]
hash冲突导致数据不准确
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v8uqJygE-1692427541190)(https://you-blog.oss-accelerate.aliyuncs.com/2023/202303132223964.png)]
查询某个变量的时候,只需要看看这些点是不是都是1,就可以大概率知道集合中是否存在了。
如果这些点,有任何一个为零,则查询的key一定不存在。
如果全部是1,则被查询的key很大概率存在。(因为使用的hash散列函数,会有碰撞冲突)
正是基于布隆过滤器的快速检测特性,我们可以在把数据写入数据库时,使用布隆过滤器做个标记。当缓存缺失后,应用查询数据库时,可以通过查询布隆过滤器快速判断数据是否存在。如果不存在,就不用再去数据库中查询了。这样一来,即使发生缓存穿透了,大量请求只会查询Rdis和布隆过滤器,而不会积压到数据库,也就不会影响数据库的正常运行。布隆过滤器可以使用Rdis实现,本身就能承担较大的并发访问压边。
hash函数冲突
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TehVDTf3-1692427541190)(https://you-blog.oss-accelerate.aliyuncs.com/2023/202303132228541.png)]
-
使用步骤
-
初始化bitmap
-
添加元素占坑位
-
判断元素是否存在
-
-
布隆过滤器误判率,为什么不要删除
布隆过滤器的误判是指多个输入经过哈希之后在相同的t位置1了,这样就无法判断究竞是哪个输入产生的,因此误判的根源在于相同的bt位被多次映射且置1。
这种情况也造成了布隆过滤器的删除问题,因为布隆过滤器的每一个bt并不是独占的,很有可能多个元素共享了某一位。
如果我们直接删除这一位的话,会影响其他的元素
特性:布隆过滤器可以添加元素,但是不能删除元素。因为删掉元素会导致误判率增加。
-
总结
- 有:很可能有
- 无:一定无
使用时最好不要让实际元素数量远大于初始化数量,一次给够,避免扩容
当实际元素数量超过初始化数量时,应该对布隆过滤器进行重建,重新分配一个size更大的过滤器,再将所有的历史元素批量add。
四、使用场景
-
解决缓存穿透的问题,和redis结合bitmap使用
-
黑名单校验,识别垃圾邮件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yDWuLolY-1692427541194)(/Users/coder/Library/Application Support/typora-user-images/image-20230313224905294.png)]
-
安全连接网址,全球数10亿的网址判断
五、尝试手写布隆过滤器
-
整体架构
-
步骤设计
redis的shebit、getbit
setbit的构建过程
gitbit查询是否存在
-
编码实现
-
案例