✅布隆过滤器有什么缺点,如何解决?
典型回答
布隆过滤器是一个非常好用的数据结构,他可以在只使用非常少的空间的情况下,实现一个过滤器的功能。但是因为他的实现原理(原理见上文),导致了他天然存在很多缺点。
1、误判
布隆过滤器有一个非常大的问题,就是存在误判的可能。也就是说,布隆过滤器可能会误判某个不存在的元素为存在(假阳性),主要是因为布隆过滤器其实底层是做了hash然后存储在不同的bit上的,而hash的结果是可能会存在冲突的,那么就会导致多个元素可能映射到相同的bit。
这个问题在介绍布隆过滤器的原理的时候讲过了,就不展开说了,主要说说怎么解决和降低这个问题。
首先,我们可以通过增加布隆过滤器的底层的bitmap中位数组的长度,来降低哈希碰撞的概率,这个就和hashmap原理类似,容量越大,冲突的概率越底。
其次,就是可以通过优化哈希函数,来降低冲突的概率,比较常见的做法就是增加哈希函数的个数,针对一个元素用多个hash函数同时做哈希之后再存储,也可以大大降低冲突的概率。** **
还有一些其他的方案,比如使用分层布隆过滤器,或者技术布隆过滤器等,但是都不常用。
最后,想要完全避免误判的发生是不可能的,不过我们可以降低误判的概率,然后在命中布隆过滤器之后,再进行数据的二次查询最最终校验,比如查数据库,查redis。
有人可能会认为,这么做是不是失去了布隆过滤器的意义,查到了竟然还要再去数据库中查一遍?
其实并不是的,因为布隆过滤器他之所以叫做过滤器,其实他的主要作用是可以把一些根本不存在的情况给他过滤掉的。因为如果布隆过滤器返回结果是不存在,那么说明他一定不存在。
所以,我们通常在一些典型的黑名单场景,适合使用布隆过滤器的。因为黑名单毕竟是少数,所以大部分用户是不会命中黑名单,所以就可以直接放行,如果有一个用户命中了黑名单,但是因为有误判,所以需要再查询数据库做二次判断。即使是这样,布隆过来器也帮我们过滤了很多不需要请求数据库的流量。
2、 无法删除元素
布隆过滤器是无法删除元素的,因为布隆过滤器无法准确的判断一个元素是否一定存在,所以他也就无法准确的删除这个元素。
还有一个原因,那就是一个元素,会通过多个hash函数哈希后存储在不同的bit上,而一个bit上存的的如果是1的话,只能说明有元素哈希后的结果在这里,但是具体有几个是不知道的。而我们想要删除这个元素的话,我们即使算出他的bit有哪几个,也不知道是不是应该把他从1设置为0,因为完全这个bit有可能是存在hash冲突,有多个元素的。
那么如何解决这个问题呢?
3、其他的问题
以上两个就是主要的问题和解决的方式,除了这些问题以外,还有一些缺点,但是我认为也不算啥缺点,只不过他适用的一些场景。比如模糊查询他不支持。
还有就是如果我们使用redis或者guava,在最开始构建的时候,需要指定一个最大容量和误判率,这两个都需要有一定的经验才能设置的好,如果设置的不合理会导致大量的冲突或者误判。
一般我们容量是预估一下最大可以存多少,比如1000万,2000万这种。然后误判率的话,我们一般设置为百分之一或者千分之一,当然,也和具体的业务有关。供大家参考。