✅布隆过滤器无法删除的问题如何解决?

✅布隆过滤器无法删除的问题如何解决?

典型回答

布隆过滤器是无法删除元素的,因为布隆过滤器无法准确的判断一个元素是否一定存在,所以他也就无法准确的删除这个元素。

其实就是一个元素,会通过多个hash函数哈希后存储在不同的bit上,而一个bit上存的的如果是1的话,只能说明有元素哈希后的结果在这里,但是具体有几个是不知道的。而我们想要删除这个元素的话,我们即使算出他的bit有哪几个,也不知道是不是应该把他从1设置为0,因为完全这个bit有可能是存在hash冲突,有多个元素的。

那么如何解决这个问题呢?


定期重建

其实,这个问题无法解决,只能换个思路,大家试想一下,无法删除的话会有什么问题呢?

无法删除就会导致某个元素已经不存在了,但是查询结果还是可以查到。那如果在布隆过滤器中查到了,我们为了避免误判,还是会去数据库查一次。

也就是说,虽然我们无法删除元素,也不会影响最终的结果,因为判断命中之后还会做二次校验。只不过随着元素删除的越来越多,会导致误判率的上升,进而导致数据库的请求量变大罢了。

那么,一般业内的解决办法是定期重建,就是每隔一段时间,基于最新的数据重新构建一个布隆过滤器,然后把他切换一下即可。

比如基于Guava的布隆过滤器,我们就可以在应用启动的时候构建,这样每次重启就是一个新的了。或者通过定时任务去构建一个新的。至于构建出新的之后,如何切换呢?很简单,我们自己维护一个map,只需要创建好新的之后,把他放到map里,key还有之前的key就可以了,。下次用的时候再来map查询,就得到一个新的了。

计数布隆过滤器

既然布隆过滤器因为每一个bit上存储为1的时候,不知道有多少个元素hash后存在了这里,所以不能删除,那么可以考虑采用计数布隆过滤器。即将布隆过滤器的位数组中的每一个位(bit),扩展为一个计数器(counter)。通常使用 3-4 位的计数器(可表示 0-15)****

  • 添加元素:不再是将位设置为 1,而是将对应位置的计数器加 1。
  • 查询元素:检查所有对应位置的计数器是否都大于 0。
  • 删除元素:将要删除元素对应位置的计数器减 1。

有点就是可以解决无法删除问题,实现起来也挺简单的。但是缺点是原本 1 个 bit 的位置,现在需要 3-4 bits(开销是原来的 300%-400%),带来了额外的开销(但相比用其他数据结构,比如 Set 存储所有元素,它仍然非常节省空间)。还有就是如果计数器只有 4 位,最大只能表示 15。如果同一个位置被添加超过 15 次,计数器会绕回(溢出),所以需要权衡占用空间和溢出的问题

布谷鸟过滤器

✅什么是布谷鸟过滤器,实现原理是什么?