Redis不可不谈之布隆过滤器
前言
布隆过滤器(Bloom Filter)一种判断手法,可以告诉你某种东西一定不存在或者可能存在。当布隆过滤器说,某种东西存在时,这种东西可能不存在;至于为什么,会在后面详细分析。当布隆过滤器说,某种东西不存在时,那么这种东西一定不存在。为什么这么肯定呢!我们也需要一起来看一下布隆过滤器的内在逻辑。
布隆过滤器相对于Set、Map 等数据结构来说,它可以更高效地插入和查询,并且占用空间更少,它也有缺点,就是判断某种东西是否存在时,可能会被误判。我们刚刚说过了,就是当判断存在的时候,结果是不确定的。但是只要参数设置的合理,它的精确度也可以控制的相对精确,只会有小小的误判概率。这也就意味着,只要参数设置合理的区间能满足一个水平置信,那么判断成功的概率也是可以接近于1的。
之前的布隆过滤器可以使用Redis中的位图操作实现,直到Redis4.0版本提供了插件功能,Redis官方提供的布隆过滤器才正式登场。布隆过滤器作为一个插件加载到Redis Server中,就会给Redis提供了强大的布隆去重功能。
提示:以下是本篇文章正文内容,下面案例可供参考
一、布隆过滤器的原理
Redis中布隆过滤器的数据结构就是一个很大的位数组和几个不一样的无偏哈希函数(能把元素的哈希值算得比较平均,能让元素被哈希到位数组中的位置比较随机)。如下图,A、B就是两个这样的哈希函数,分别对“大帅哥”和“大美女”这两个元素进行哈希,位数组的对应位置则被设置为1:
向布隆过滤器中添加元素时,会使用多个无偏哈希函数对元素进行哈希,算出一个整数索引值,然后对位数组长度进行取模运算得到一个位置,每个无偏哈希函数都会得到一个不同的位置。再把位数组的这几个位置都设置为1,这就完成了bf.add命令的操作。向布隆过滤器查询元素是否存在时,和添加元素一样,也会把哈希的几个位置算出来,然后看看位数组中对应的几个位置是否都为1,只要有一个位为0,那么就说明布隆过滤器里不存在这个元素。如果这几个位置都为1,并不能完全说明这个元素就一定存在其中,有可能这些位置为1是因为其他元素的存在,这就是布隆过滤器会出现误判的原因。
二、布隆过滤器使用
1.基本使用
在Redis中,布隆过滤器有两个基本命令,分别是:
bf.add:添加元素到布隆过滤器中,类似于集合的sadd命令,不过bf.add命令只能一次添加一个元素,如果想一次添加多个元素,可以使用bf.madd命令。
bf.exists:判断某个元素是否在过滤器中,类似于集合的sismember命令,不过bf.exists命令只能一次查询一个元素,如果想一次查询多个元素,可以使用bf.mexists命令。
> bf.add one-more-filter fans1
(integer) 1
> bf.add one-more-filter fans2
(integer) 1
> bf.add one-more-filter fans3
(integer) 1
> bf.exists one-more-filter fans1
(integer) 1
> bf.exists one-more-filter fans2
(integer) 1
> bf.exists one-more-filter fans3
(integer) 1
> bf.exists one-more-filter fans4
(integer) 0
> bf.madd one-more-filter fans4 fans5 fans6
1) (integer) 1
2) (integer) 1
3) (integer) 1
> bf.mexists one-more-filter fans4 fans5 fans6 fans7
1) (integer) 1
2) (integer) 1
3) (integer) 1
4) (integer) 0
2.进阶使用
上面的例子中使用的布隆过滤器只是默认参数的布隆过滤器,它在我们第一次使用bf.add命令时自动创建的。Redis还提供了自定义参数的布隆过滤器,想要尽量减少布隆过滤器的误判,就要设置合理的参数。
在使用bf.add命令添加元素之前,使用bf.reserve命令创建一个自定义的布隆过滤器。bf.reserve命令有三个参数,分别是:
key:键
error_rate:期望错误率,期望错误率越低,需要的空间就越大。
capacity:初始容量,当实际元素的数量超过这个初始化容量时,误判率上升。
上面就是一个推导过程,其中m,n的关系就能反映误差率和空间的关系,m,n就是空间的一个表征。
总结
布隆过滤器的使用是Redis的一个重中之重,尤其是去了解布隆过滤器的原理,明确在判断存在时误差率和空间的关系,而误差率是和空间相关的,空间及时slot数和元素数的一种关系。