深入Redis(五)布隆过滤器

布隆过滤器

HyperLogLog可以进行估数,非常具有价值,可以解决很多精确度要求不高的统计需求。

但是如果我们想知道某一值是不是在HyperLogLog结构内则无能为力了,因为HyperLogLog没有提供类似pfcontains这种方法。

比如,我们在使用新闻客户端看新闻时,它会不断推荐新的内容,每次推荐时都要去重,那么如何实现推送去重?

我们会想到,服务器记录了用户看过的所有历史纪录,推荐系统每次都从用户的历史纪录内筛选已经看过的记录,但用户量很大并且每个用户看过的新闻又很多时,推荐系统的去重功能在性能上不一定能跟的上。并且如果历史记录保存在关系数据库中,去重就要频繁的对数据库进行exists查询,当并发量上来时,数据库首先会扛不住压力。

再其次可能会想到缓存,但这么大量的历史纪录全部缓存下来,浪费的存储空间就太大了,并且这个存储空间是线性增长的,能撑得住一个月,不一定撑得了几年,但不用缓存,性能又跟不上,那么怎么办呢?

布隆过滤器(Bloom Filter)就是专门来解决这种问题的,它起到去重的同时,在空间上还能节省90%以上,只是存在一定的误判概率。

布隆过滤器是什么?

可理解为一个不那么精确的set结构,当使用contains方法判断某个对象是否存在时,可能会误判,但是也不是特别不精确,只要参数设置合理,精确度可以控制得足够精准。

当布隆过滤器说某个值存在时,它可能不存在;但当它说某个值不存在时,它一定不存在。

套用在上述情景中,布隆过滤器能准确过滤掉已看过的内容,没看过的内容可能会过滤掉很小一部分,这样就能保证推荐给用户的都是无重复的。

Redis中的Bloom Filter

Redis官方提供的布隆过滤器到4.0提供插件功能后才正式登场,布隆过滤器作为一个插件加载到Redis Server中,给Redis提供了强大的布隆去重功能。

git clone git://github.com/RedisLabsModules/rebloom

cd rebloom

make # 在当前路径下生成rebloom.so文件

redis-server --loadmodule /path/to/rebloom.so # 启动redis服务器并使用前面生成的文件,或者在配置文件中添加"loadmodule /path/to/rebloom.so"

基本使用

布隆过滤器有两个基本指令,bf.add添加元素,bf.exists查询元素是否存在,bf.madd一次添加多个元素,bf.mexists一次查询多个元素。

127.0.0.1:6379> bf.add codehole user1
(integer) 1
127.0.0.1:6379> bf.add codehole user2
(integer) 1
127.0.0.1:6379> bf.add codehole user3
(integer) 1
127.0.0.1:6379> bf.exists codehole user1
(integer) 1
127.0.0.1:6379> bf.exists codehole user2
(integer) 1
127.0.0.1:6379> bf.exists codehole user3
(integer) 1
127.0.0.1:6379> bf.exists codehole user4
(integer) 0
127.0.0.1:6379> bf.madd codehole user4 user5 user6
1) (integer) 1
2) (integer) 1
3) (integer) 1
127.0.0.1:6379> bf.mexists codehole user4 user5 user6 user7
1) (integer) 1
2) (integer) 1
3) (integer) 1
4) (integer) 0

注意布隆过滤器对见过的元素肯定不会误判,只会误判没见过的元素。

布隆过滤器在第一次add的时候自动创建基于默认参数的过滤器,Redis还提供了自定义参数的布隆过滤器。

在add之前使用bf.reserve指令显式创建,其有3个参数,key,error_rate, initial_size,错误率越低,需要的空间越大,error_rate表示预计错误率,initial_size参数表示预计放入的元素数量,当实际数量超过这个值时,误判率会上升,所以需要提前设置一个较大的数值来避免超出。默认的error_rate是0.01,initial_size是100。

注意事项

initial_size估计的过大会浪费存储空间,因此在使用前要尽可能精确估计好元素数量+冗余空间。

error_rate越小,需要的存储空间越大。

原理

每个布隆过滤器对应到Redis的数据结构中就是一个大型的位数组和几个不同的无偏hash函数,无偏表示分布均匀。

添加key时,使用多个hash函数对key进行hash运算得到一个整数索引值,对位数组长度进行取模运算得到一个位置,每个hash函数都会得到一个不同的位置,将这几个位置都置1就完成了add操作。

查询同理,只要有一位是0就表示这个key不存在,但如果都是1,则不一定存在对应的key。

空间占用估计

布隆过滤器的空间占用有一个简单的计算公式,但推导比较繁琐。布隆过滤器有两个参数,预计元素数量n,错误率f,公式得到两个输出,位数组长度L(即存储空间大小bit),hash函数的最佳数量k。

k = 0.7*(1/n)
f = 0.6185^(L/n)
  1. 位数组相对长度越长,错误率越低;
  2. 位数组相对长度越长,需要的hash函数越多;
  3. 当一个元素平均需要一个字节(8bit)的指纹空间时(L/n=8),错误率大约为2%。

实际元素超出时,误判率会怎样变化?

f = (1-0.5^t)^k  # t为实际元素与预计元素的倍数
  1. 当错误率为10%时,倍数比为2时,错误率接近40%;
  2. 当错误率为1%,倍数比为2时,错误率15%;
  3. 当错误率为0.1%,倍数为2时,错误率5%。

布隆过滤器的其它应用

爬虫URL去重,NoSQL数据库领域降低数据库的IO请求数量,邮箱系统的垃圾邮件过滤。

原文地址:https://www.cnblogs.com/ikct2017/p/9499364.html

时间: 2024-10-09 08:54:18

深入Redis(五)布隆过滤器的相关文章

redis之布隆过滤器

布隆过滤器是什么? 布隆过滤器可以理解为一个不怎么精确的 set 结构,当你使用它的 contains 方法判断某个对象是否存在时,它可能会误判.但是布隆过滤器也不是特别不精确,只要参数设置的合理,它的精确度可以控制的相对足够精确,只会有小小的误判概率 布隆过滤器基本使用 布隆过滤器有二个基本指令,bf.add 添加元素,bf.exists 查询元素是否存在,如果想要一次添加多个,就需要用到 bf.madd 指令.同样如果需要一次查询多个元素是否存在,就需要用到 bf.mexists 指令. 1

Redis05——Redis高级运用(管道连接,发布订阅,布隆过滤器)

Redis高级运用 一.管道连接redis(一次发送多个命令,节省往返时间) 1.安装nc yum install nc -y 2.通过nc连接redis nc localhost 6379 3.通过echo向nc发送指令 echo -e "set k2 99\nincr k2\n get k2" |nc localhost 6379 二.发布订阅(pub/Sub) publish channel message subscribe channel 三.事务(transactions)

7.【Redis系列】Redis的高级应用-布隆过滤器

原文:7.[Redis系列]Redis的高级应用-布隆过滤器 拿今日头条来说,它会不停的给我们推荐新的新闻,每次推荐都要去重,过滤掉我们之前看过的内容,今日头条如何做到去重呢,我们上面的HyperLogLog虽然能去重,但是没有办法确认这个新闻有没有被浏览 过,没有pfcontains的方法.有没有更好的解决方案呢? Redis为我们准备了布隆过滤器,是专门用来解决这种去重问题的,它在起去重功能的同时,空间上还可以节约90%,只是稍微有一定的误判率. 什么是布隆过滤器 布隆过滤器可以理解为稍微不

第三百五十八节,Python分布式爬虫打造搜索引擎Scrapy精讲—将bloomfilter(布隆过滤器)集成到scrapy-redis中

第三百五十八节,Python分布式爬虫打造搜索引擎Scrapy精讲-将bloomfilter(布隆过滤器)集成到scrapy-redis中,判断URL是否重复 布隆过滤器(Bloom Filter)详解 基本概念 如果想判断一个元素是不是在一个集合里,一般想到的是将所有元素保存起来,然后通过比较确定.链表,树等等数据结构都是这种思路. 但是随着集合中元素的增加,我们需要的存储空间越来越大,检索速度也越来越慢.不过世界上还有一种叫作散列表(又叫哈希表,Hash table)的数据结构.它可以通过一

【redis】redis添加bloom filter布隆过滤器插件

前言 redis在4.0版本以后可通过插件的形式添加布隆过滤器,以下为具体操作. 操作 在https://github.com/RedisBloom/RedisBloom下载最新的release源码,在编译服务器进行解压编译: tar zxvf RedisBloom-1.1.1.tar.gz cd RedisBloom-1.1.1 make 得到动态库rebloom.so 启动redis时,如下启动即可加载bloom filter插件 ./redis-server /usr/local/redi

我的开源项目-------远程布隆过滤器服务

由于项目需要 所有的downserver node 都需要访问一个公共的布隆过滤器 也就是要做一个跨网络挺供的布隆过滤器服务中间产品. 同时要保证非常非常高的实时性 所以在这里 所以现在必须要做一个这样的中间服务系统.主要实现如下功能: 1 客户端远程传入一个需要存入读或者写入布隆过滤器的string.服务器端提供一个布隆过滤器服务 通过N个哈希函数映射到相应的bit位写入或者读出函数. 2 拥有丰富的配置 [具体看开源项目需要] 3 要拥有主从服务配置和持久化模式[这2种可以借鉴REDIS服务

海量数据处理利器之布隆过滤器

看见了海量数据去重,找到停留时间最长的IP等问题,有博友提到了Bloom Filter,我就查了查,不过首先想到的是大叔,下面就先看看大叔的风采. 一.布隆过滤器概念引入 (Bloom Filter)是由布隆(Burton Howard Bloom)在1970年提出的.它实际上是由一个很长的二进制向量和一系列随机映射函数组成,布隆过滤器可以用于检索一个元素是否在一个集合中.它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率(假正例False positives,即Bloom

布隆过滤器认知

布隆过滤器 (Bloom Filter)是由Burton Howard Bloom于1970年提出,它是一种space efficient的概率型数据结构,用于判断一个元素是否在集合中. 看看下面几个问题: 字处理软件中,需要检查一个英语单词是否拼写正确 在 FBI,一个嫌疑人的名字是否已经在嫌疑名单上 在网络爬虫里,一个网址是否被访问过 邮箱垃圾邮件过滤功能 以上这些场景有个共同的问题:如何查看一个东西是否在有大量数据的池子里面. 通常做法有以下几种思路: 数组 链表 树.平衡二叉树.Trie

布隆过滤器的方式解决缓存穿透问题

1.原理 布隆过滤器的巨大用处就是,能够迅速判断一个元素是否在一个集合中.因此他有如下三个使用场景: 网页爬虫对URL的去重,避免爬取相同的URL地址 反垃圾邮件,从数十亿个垃圾邮件列表中判断某邮箱是否垃圾邮箱(同理,垃圾短信) 缓存穿透,将所有可能存在的数据缓存放到布隆过滤器中,当黑客访问不存在的缓存时迅速返回避免缓存及DB挂掉. OK,接下来我们来谈谈布隆过滤器的原理 其内部维护一个全为0的bit数组,需要说明的是,布隆过滤器有一个误判率的概念,误判率越低,则数组越长,所占空间越大.误判率越