这篇博客我们来说一下布隆过滤器
之前我们在讲redis缓存穿透的时候说可以使用布隆过滤器来解决这个问题
那么我们先来简单复习一下什么时缓存穿透
(一)复习缓存穿透
我们都知道redis可以作为mysql的缓存帮忙抵挡大部分的请求,但是当redis中查找不到数据时就会去数据库中查找。
如果数据库中查找到了就会写到redis中,但是也会存在一些找不到的情况,如果找不到的话,后端又重复的大量发送这个请求,就会一次次的访问数据库,就有可能会导致缓存穿透(服务器挂了),所以针对缓存穿透,我们有几种处理办法
1.我们即使在数据库中查不到,也把他写到redis中,只不过值为null
2.提前校验,如果不存在就不查询了
3.使用布隆过滤器,把不存在的数据大部分都过滤掉
(二)布隆过滤器
我们注意刚刚的词,把不存在的数据“大部分”都过滤掉,那为什么是大部分呢?因为布隆过滤器存在误判性,所以在他的使用场景也在一些要求不太严格的场景下(允许一定的误判率)
1.什么是布隆过滤器
布隆过滤器是一种数据结构,是由一个位数组和多个哈希函数构成的
使用位数组可以很好的节省空间
2.工作原理
首先我们的每个位初始值都是0,每当我们存入一个元素时,我们会通过哈希函数并且模上他的大小计算出我们要把那个地方赋值为1
当然一个哈希函数虽然可以,但是他的结果是很不准确的,所以我们有多个哈希函数,我们的元素要对这些哈希函数都进行运算取模
3.哈希冲突
但是我们在学哈希表的时候,我们知道会发生哈希冲突,而这里我们的位数组很明显也无法使用开散列来解决,这就会导致会有一定的错误概率,即报告元素可能在集合中,但实际上并未被插入过。但布隆过滤器不会出现漏报(False Negative),即如果布隆过滤器说元素不在集合中,则这个结论是绝对正确的。
上述就说明了会有可能发生哈希冲突
这时我们来查一个没有的元素,我们可以正确判断这个元素是没有的,因为他有一位是0,但是也可能全都为1
就像这样,如果全都为1,布隆过滤器就会认为我们是可以查到的,就会放行
所以布隆过滤器有一句话: 对于结果来说,不存在一定不存在,存在不一定存在
4.解决办法
1)我们可以扩大位数组的长度,让哈希冲突的概率变小
2)增加哈希函数个数
5.布隆过滤器的优缺点
优点:节省空间,我们适用位数组来存储数据,相较于其他数据结构,空间小了很多
查询速度快,只需要进行几次哈希运算,并且看看对应位置的值即可
缺点:随着元素的增多,发生哈希冲突概率变大,同时误判率也会变大
不可删除,我们无法把位数组中的1改变为0,因为我们不知道这个1是通过哪一个元素置为1的