写在前面:
又是很久没更新了,今天刚好看到了关于布隆过滤器的一些讨论,笔者刚好借助CSDN发表对布隆过滤器的一些理解。
什么是布隆过滤器:
物有本末,事有终始,知其先后,则近道矣。
首先,我们需要明白,布隆过滤器是什么呢?为什么要存在布隆过滤器?而布隆过滤器又解决了一些什么问题呢?布隆过滤器的弊端是什么呢?
布隆过滤器:
一言以蔽之,用bit位(因为1字节 = 8bit,所以称为bit数组)用其中某一位来表示某个值是否存在(建立映射,1代表已经映射,0代表还未映射)。这样说可能比较抽象,可以看下图所示:
为什么要存在布隆过滤器:
对于Java Coder来说,一定使用过HashMap这个数据结构,所以看到此处的时候肯定会思考,这布隆过滤器不就是HashMap,用key,value来做映射么?我用JDK自带的HashMap不香吗?为什么要使用这个啥布隆过滤器?
所以此处需要考虑,HashMap来存储为什么不行?
举个很简单的例子:HashMap<String,String> map = new HashMap(); 这样的方式来存储一个对象要用多少个字节?而布隆过滤器只需要一个bit位,而一个字节 = 8个bit位。并且在一些大型项目中数据量可能达到百万、千万、亿的数据量,此时使用HashMap可能直接把内存撑爆,导致OOM。所以布隆过滤器的优势就体现出来了。
布隆过滤器又解决了一些什么问题:
各种判断是否重复或者存在的场景(需要能接受容错的情况,不能保证100%的准确):缓存穿透
IP过滤(黑名单)
秒杀的重复下单
等等......
布隆过滤器的弊端:
弊端1:
上面既然提到了需要能接受容错的情况,不能保证100%的准确.
为什么是会有容错的情况呢?我们知道HashMap是通过hash定位再通过equals确保是否一致。如果Hash冲突就链表链起来。而布隆过滤器是不存在这种情况,所以为了尽量避免Hash产生碰撞的情况,就出现了多次不同的Hash运算,最终通过N次不同的Hash运算定位到bit数组的不同下标位置,尽量减少Hash碰撞出现的容错问题(但是也没办法去避免)。
弊端2:
再考虑,删除的问题,是没办法删除的,因为所有数据是共享一个bit数组的。
弊端3:
再考虑,拿缓存穿透做案例,如果不存在的key就直接返回不存在,所以需要系统初始化的时候就把所有需要放入缓存中的数据查询一次,添加到布隆过滤器中(不过也不是算是很大的弊端,因为往往系统初始化的时候需要做缓存做预热,顺带做布隆过滤器的初始化)
弊端4:
再考虑,如果一个值需要做几次Hash运算,那么就会占用bit数组的几个下标,这样就很容易把bit数组给填满1,这样下来,容错的几率大大上升(因为判断是否存在,就是判断此值映射的bit数组的下标是否都是1)。所以对于bit数组的长度也需要根据项目定制,到底几次不同的Hash算法比较合适也需要根据算法定制。如下图所示:

具体的bit数组长度算法为:
具体的HASH次数算法为:
具体的容错次数:
注:对于算法来说,笔者也没特意去推理过,因为暂时没有使用的业务场景,所以没有去仔仔细细的推理算法。如果读者有需要去深入理解算法的话,可以看下面的链接:
总结:
最后,如果本帖对您有一定的帮助,希望能点赞+关注+收藏!您的支持是给我最大的动力,后续会一直更新各种框架的使用和框架的源码解读~!