详细解析Redis中的布隆过滤器及其应用

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。redis

什么是布隆过滤器

布隆过滤器(Bloom Filter)是由Howard Bloom在1970年提出的一种比较巧妙的几率型数据结构,它能够告诉你某种东西必定不存在或者可能存在。当布隆过滤器说,某种东西存在时,这种东西可能不存在;当布隆过滤器说,某种东西不存在时,那么这种东西必定不存在。数据库

布隆过滤器相对于Set、Map 等数据结构来讲,它能够更高效地插入和查询,而且占用空间更少,它也有缺点,就是判断某种东西是否存在时,可能会被误判。可是只要参数设置的合理,它的精确度也能够控制的相对精确,只会有小小的误判几率。数组

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。缓存

Redis中布隆过滤器

以前的布隆过滤器可使用Redis中的位图操做实现,直到Redis4.0版本提供了插件功能,Redis官方提供的布隆过滤器才正式登场。布隆过滤器做为一个插件加载到Redis Server中,就会给Redis提供了强大的布隆去重功能。微信

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。数据结构

布隆过滤器的基本使用

在Redis中,布隆过滤器有两个基本命令,分别是:函数

  • bf.add:添加元素到布隆过滤器中,相似于集合的sadd命令,不过bf.add命令只能一次添加一个元素,若是想一次添加多个元素,可使用bf.madd命令。
  • bf.exists:判断某个元素是否在过滤器中,相似于集合的sismember命令,不过bf.exists命令只能一次查询一个元素,若是想一次查询多个元素,可使用bf.mexists命令。

好比:spa

> 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

上面的例子中,没有发现误判的状况,是由于元素数量比较少。当元素比较多时,可能就会发生误判,怎么才能减小误判呢?插件

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。rest

布隆过滤器的高级使用

上面的例子中使用的布隆过滤器只是默认参数的布隆过滤器,它在咱们第一次使用bf.add命令时自动建立的。Redis还提供了自定义参数的布隆过滤器,想要尽可能减小布隆过滤器的误判,就要设置合理的参数。

在使用bf.add命令添加元素以前,使用bf.reserve命令建立一个自定义的布隆过滤器。bf.reserve命令有三个参数,分别是:

  • key:键
  • error_rate:指望错误率,指望错误率越低,须要的空间就越大。
  • capacity:初始容量,当实际元素的数量超过这个初始化容量时,误判率上升。

好比:

>  bf.reserve one-more-filter 0.0001 1000000
OK

若是对应的key已经存在时,在执行bf.reserve命令就会报错。若是不使用bf.reserve命令建立,而是使用Redis自动建立的布隆过滤器,默认的error_rate是 0.01,capacity是 100。

布隆过滤器的error_rate越小,须要的存储空间就越大,对于不须要过于精确的场景,error_rate设置稍大一点也能够。布隆过滤器的capacity设置的过大,会浪费存储空间,设置的太小,就会影响准确率,因此在使用以前必定要尽量地精确估计好元素数量,还须要加上必定的冗余空间以免实际元素可能会意外高出设置值不少。总之,error_ratecapacity都须要设置一个合适的数值。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

布隆过滤器的原理简介

了解了布隆过滤器的使用,咱们再来介绍一下布隆过滤器的原理,作到“知其然,知其因此然”。

Redis中布隆过滤器的数据结构就是一个很大的位数组和几个不同的无偏哈希函数(能把元素的哈希值算得比较平均,能让元素被哈希到位数组中的位置比较随机)。以下图,A、B、C就是三个这样的哈希函数,分别对“OneMoreStudy”和“万猫学社”这两个元素进行哈希,位数组的对应位置则被设置为1:

向布隆过滤器中添加元素时,会使用多个无偏哈希函数对元素进行哈希,算出一个整数索引值,而后对位数组长度进行取模运算获得一个位置,每一个无偏哈希函数都会获得一个不一样的位置。再把位数组的这几个位置都设置为1,这就完成了bf.add命令的操做。

向布隆过滤器查询元素是否存在时,和添加元素同样,也会把哈希的几个位置算出来,而后看看位数组中对应的几个位置是否都为1,只要有一个位为0,那么就说明布隆过滤器里不存在这个元素。若是这几个位置都为1,并不能彻底说明这个元素就必定存在其中,有可能这些位置为1是由于其余元素的存在,这就是布隆过滤器会出现误判的缘由。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

布隆过滤器的应用

解决缓存击穿的问题

通常状况下,先查询缓存是否有该条数据,缓存中没有时,再查询数据库。当数据库也不存在该条数据时,每次查询都要访问数据库,这就是缓存击穿。缓存击穿带来的问题是,当有大量请求查询数据库不存在的数据时,就会给数据库带来压力,甚至会拖垮数据库。

可使用布隆过滤器解决缓存击穿的问题,把已存在数据的key存在布隆过滤器中。当有新的请求时,先到布隆过滤器中查询是否存在,若是不存在该条数据直接返回;若是存在该条数据再查询缓存查询数据库。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

黑名单校验

发现存在黑名单中的,就执行特定操做。好比:识别垃圾邮件,只要是邮箱在黑名单中的邮件,就识别为垃圾邮件。假设黑名单的数量是数以亿计的,存放起来就是很是耗费存储空间的,布隆过滤器则是一个较好的解决方案。把全部黑名单都放在布隆过滤器中,再收到邮件时,判断邮件地址是否在布隆过滤器中便可。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

相关文章
相关标签/搜索