基于Redis的布隆过滤器的实现

13 篇文章 2 订阅
2 篇文章 0 订阅

项目简介

包含一个基于Redis的布隆过滤器的实现,以及应用到Scrapy中的Demo。

地址:BloomFilterRedis


布隆过滤器

网上有很多介绍,推荐《数学之美》,介绍的很详尽,此处不再赘述。


哈希函数

布隆过滤器中需要n个哈希函数,我使用的是Arash Partow提供的常见哈希函数


建立在Redis上的布隆过滤器

Redis中有一个数据结构叫做Bitmap(下方有官网详解),它提供一个最大长度为512MB(2^32)的位数组。我们可以把它提供给布隆过滤器做位数组。

根据《数学之美》中给出的数据,在使用8个哈希函数的情况下,512MB大小的位数组在误报率万分之五的情况下可以对约两亿的url去重。而若单纯的使用set()去重的话,以一个url64个字节记,两亿url约需要128GB的内存空间,不敢想象。

我使用的策略是使用哈希函数算出的哈希值对2^32取模,填入bitmap中。


Reids之Bitmap

以下内容翻译自官网http://www.redis.cn/topics/data-types-intro.html#bitmaps
英语水平有限,有些地方选择了意译,大佬路过还请不吝赐教,先行谢过~

Bitmap不是一个确切的数据类型,而是基于String类型定义的一系列面向位操作的方法。因为String是二进制安全的并且它们的最大长度是512MB,
所以String类型很合适去作为一个2^32长度的位数组。

位操作方法可以被分为两组:一、对单一位的操作,比如设置某一位为1或0,或者得到这一位的值;二、对一组位的操作,比方说计算一定范围内的1的个数(比如计数)
bitmap一个最大的优势是它通常能在存储信息的时候节省大量空间。比方说一个用增量ID来辨别用户的系统,可以用仅仅512MB的空间来标识40亿个用户是否想要接受通知。

使用SETBIT和GETBIT命令来对位进行置数和检索:

> setbit key 10 1
(integer) 1
> getbit key 10
(integer) 1
> getbit key 11
(integer) 0

SETBIT 如上所示,意思是将第10位置位为1,第二个参数可为0或1。如果设置的位超出了当前String的长度,那么会自动增长。(最长2^32,下同)
GETBIT 如上所示,返回第10位和第11位的数据,分别是1和0。如果查找的位超出了当前String的长度,那么会返回0。

接下来是三个对一组位进行操作的命令:
BITOP 执行不同字符串之间的逐位操作。所提供的操作有AND,OR,XOR和NOT。BITCOUNT
BITCOUNT 计数,返回bitmap里值为1的位的个数.
BITPOS 返回第一个0或1的位置
BITPOS和BITCOUNT不仅可以作用于整个bitmap,还可以作用于一定的范围,下面是一个BITCOUNT的例子:

> setbit key 0 1
(integer) 0
> setbit key 100 1
(integer) 0
> bitcount key
(integer) 2

应用实例略……


整合进Scrapy

Scrapy中可以在settings.py中通过DUPEFILTER_CLASS配置过滤器,github上给出了示例工程


验证

起初的验证策略是:使用scrapy框架从一个百度百科页面出发,提取页面内其它百科词条的链接,在过滤器内将过滤掉的url记录在本地文件
filted.txt中,将正确请求的到的结果存入mongoDB。

在起初测试时发现filted.txt中记录的过滤掉的url中百分之九十九都不在mongoDB内,注意到已过滤掉约1万条url,而mongoDB中仅有300条,
使用bitcount key命令查看redis中的bitmap中的值为1的位的个数,发现有约10万。而mongoDB中的300条数据至多置位300*8=2400位,显
然哪里出了问题。经分析,这是因为大量经过过滤器的请求尚存在于scrapy的请求队列中,未被发出,所以mongoDB里也不会有相应记录。

所以为了验证布隆过滤器的可靠性,在过滤器过滤前将所有的url都存入allurl.txt文件,等文件内url达到一定规模后,与filted.txt进行
相应处理——编写脚本计算误报率。经验证,在对百度百科约70万条url进行处理后,过滤约40万条,误判量为0。此验证规模甚小,但笔者近期无具体大
规模去重需求,欢迎有需求或有兴趣的同仁使用并反馈。

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Redis布隆过滤器Redis Bloom Filter)是一种基于概率数据结构的空间效率高、查询效率快的数据过滤器。它主要用于判断一个元素是否存在于一个大型集合中,具有低内存消耗和快速查询的特点。 布隆过滤器的原理是利用多个哈希函数和一个位数组来表示集合中的元素。当一个元素被加入到布隆过滤器中时,会通过多个哈希函数计算出多个哈希值,并将对应的位数组位置设为1。当需要判断一个元素是否存在时,同样通过多个哈希函数计算出多个哈希值,并检查对应的位数组位置是否都为1。如果有任何一个位置为0,则可以确定该元素不存在于集合中;如果所有位置都为1,则可能存在于集合中,但并不确定。 Redis布隆过滤器通过提供以下几个命令来实现: 1. BF.ADD:将一个元素添加到布隆过滤器中。 2. BF.EXISTS:判断一个元素是否存在于布隆过滤器中。 3. BF.MADD:批量添加多个元素到布隆过滤器中。 4. BF.MEXISTS:批量判断多个元素是否存在于布隆过滤器中。 需要注意的是,布隆过滤器在判断元素存在时可能会出现误判,即判断元素存在但实际上不存在。这是因为布隆过滤器的位数组中可能存在碰撞,多个元素计算得到的位数组位置可能相同。因此,在使用布隆过滤器时需要权衡误判率和内存消耗之间的关系,并根据具体场景进行调整。 Redis布隆过滤器可以应用于一些需要快速判断元素是否存在的场景,例如缓存穿透的防护、URL去重、爬虫过滤等。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孔天逸

没有钱用,只能写写博客这样子~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值