前言
上次谈到redis的缓存的缓存穿透问题。当时我们谈到了布隆过滤器,这次我们就详细谈谈布隆过滤器。在学习布隆过滤器之前,我们要有一些哈希算法的知识(如果没有可以看一下我的上一篇文章)。
利用了哈希算法的压缩性和离散性。
什么是布隆过滤器?
布隆过滤器,本质就是一个只存 “1”和“0”的数组。利用哈希算法往这个数组里存值。通过这个10数组判断是否存过这个实体。
这样说起来还是有些模糊,我们通过他的存值过程来理解一下这个结构。
向布隆过滤器中存数据(布隆过滤器的初始化)
过程:进行多次哈希,每次哈希的哈希值对这个数组的长度取余(这样这个哈希值就一定能找到在这个数组上的位置)将这个数组中对应的位置变成1。
图解:
1.放入第一个实体的过程。
1)第一次进行哈希。
2)进行哈希后,将数组的值进行改变。
3)重复上述过程,这个实体就被放入这个布隆过滤器中了。
哈希的次数越多,放一个实体和判断一个实体是否存在的时间越长,但误判率越低。这里我们以4次哈希举例子。重复上述过程4次后,这个实体就这样被放到布隆过滤器中了。
2.放入第二个实体的过程。
同理,我们放入实体2,网上大部分的图将这个实体2放到上面了,我感觉把它放到下面会比较清晰就放到下面了。大家在看到这里的时候可能会看着这个线比较多比较乱,但是这个地方线不是重要的东西,而这个10数组才重要。Ps:这里特意将实体和实体2的第一次哈希都放到了第二个位置,模拟哈希冲突。
重复上面的过程,将这些实体都放入这个布隆过滤器中(这里我们以两个实体为例)。
布隆过滤器完成初始化
此时布隆过滤器已经完成了他的初始化。现在布隆过滤器就是这样的一个结构。
使用布隆过滤器进行存在判断
过程:现在布隆过滤器已经完成了初始化。现在来了一个实体3,使用布隆过滤器判断实体3是否存在。
当一个实体3来了,进行上面相同的哈希操作(这里4次),发现哈希打到的地方都为1说明这个实体存在,当这4次哈希里有一个为0说明不存在。
这个实体3,经过前三次哈希都和实体相同,第四次哈希在一个0处。此时说明实体3和实体不是一个实体。当然布隆过滤器只能判断来的这个实体3是否存在,不能判断他和谁相等。
但是还有一种情况:
第四次的地方也是1,但是我们的实体3其实是不存在我们这个布隆过滤器中的,但此时布隆过滤器也会判定他存在。
因为前三次的哈希与实体1有了碰撞,第四次哈希与实体2有了碰撞。这样就产生了误判的情况。当你哈希的次数多就会减少这种碰撞,从而减少误判率。
上述就是布隆过滤器的初始化和布隆过滤器的使用过程了。
缺点:
上述的初始化过程不难看出,布隆过滤器的缺点就是不能删除,如果我们删除实体1,将放入实体1时变为1的0重新变回去的话,那么实体2第一次哈希(在第一次哈希的时候与实体1有了冲突)的地方也变回去了,这样也把实体2给删除了,此时布隆过滤器就已经被破坏掉了。即实体2在进来进行判断的时候,布隆过滤器就会判断实体2也不存在。所以当删除的时候就要重新构造布隆过滤器了。
总结:
布隆过滤器用一串01数组(极小的空间)就将大量的数据是否存在的信息存储了起来,通过这个过滤器可以在查询数据库之前,先过滤掉大量的不存在的数据的请求,大量减小了数据库的压力。
一点絮叨:
作文之时,生怕自己的理解出现问题,又恐自己的文笔不能将自己的意思表达清楚而误导大家,但文中难免有不足之处,希望各位朋友能够在评论区留言评论或与我私聊沟通。
正像周志明前辈在《深入理解java虚拟机》中说的,“写书和写程序一样,作品一定都是不完美的,因为不完美,我们才有不断追求完美的动力”。
无名小辈,才疏学浅,希望这篇文章能够给您带来帮助,希望各位前辈多多指点和批评。