赞
踩
我们会遇到一些场景,判断元素是否在集合中。
我们可以采用的方案有set。我们来看这两个方案的优缺点
如果我们使用set来进行判断元素是否在集合中,那么假设每一个元素的32Bit(2^24 ≈ 1600万; 2^32 ≈ 42亿),
假设我们存储1亿个不重复的元素那么我们需要 100 000 000 * 32 /8/1024/1024 ≈ 381MB;
布隆过滤器的空间占有有一个简单的计算公式,但是推到比较繁琐。布隆过滤器有两个参数,预计元素数量N,错误率f,公式得到两个输出。为位数组长度L(即布隆过滤器占用的空间Bit长度),这里k表示hash函数的最佳数量。
k = 0.7*(L/n)
f = 0.6185^(L/n)
这里我们假设错误率为1%,那么我们在1亿个不重复元素中判断元素是否存在,需要的空间
f = 0.01 = 0.6185 ^(L/100 000 000)
L = 9.585 * 100 000 000 = 9585 000 000 bit = 958 500 000/8/1024/1024 ≈ 114MB
并且set需要的内存是线性增长的如果单个元素的字节很多那么需要使用的内存是爆炸行的增长,
而单个元素的字节数并不会影响布隆过滤器(对元素进行hash)。所以在大量数据允许有误差的情况下,布隆过滤器
是首选,如果不允许有错误率并且数据量小,那么采用集合set也是一种很好的方案。
解释
添加元素到指定键键的布隆过滤器。
如果键不存在先创建键。
返回1表示元素添加成功
0表示元素已经存在本次不添加
用法 bf.add key element
示例
127.0.0.1:6379> bf.add key1 123
(integer) 1
127.0.0.1:6379> bf.add key1 123
(integer) 0
解释
判断元素是否存在于键的类型为布隆过滤器中
1: 存在
0: 不存在
用法 bf.exists key element
示例
127.0.0.1:6379> bf.add key1 123
(integer) 1
127.0.0.1:6379> bf.exists key1 123
(integer) 1
redis4.0.0及之后的版本,可以在redis启动的时候加载布隆过滤器模块,以支持布隆过滤器。
在github下载一个redisBloom稳定的版本: https://github.com/RedisBloom/RedisBloom
下载解压后的目录/usr/soft/redisBloom-2.2.2
在这个目录下执行 make
可以看到编译出了一个 redisbloom.so
启动redis服务并且加载上面的模块(模块地址/usr/soft/redisBloom-2/redisbloom.so)
redis-server /usr/local/etc/redis.conf --loadmodule /usr/soft/redisBloom-2/redisbloom.so
//启动成功后,我们可以查看一下模块是否被加载成功
127.0.0.1:6379> module list
1) 1) "name"
2) "bf"
3) "ver"
4) (integer)20202
//可以看到模块加载成功了。
虽然而这都是在大数据量下的数据判断,但是侧重点会不同一些。
布隆过滤器关注元素是否在一个大的集合中;hyperLogLog关注
集合的数量,hyperLogLog可以根据pfadd的返回值判断元素是否存在,
但是结果不是幂等的。
从最上面我们直到布隆过滤器的是由一个很长的位数组和k个hash函数组成的,
那么他们是怎么工作的呢?
当添加一个元素的时候,使用上面的k个hash函数分别计算得到k个整型索引,
每个索引对位数组长度进行取模运算得到各自的位置,将这些位置都置为1。
判断是否存在就是通过上面的k个hash计算索引,取模,取模结果的所有位
都是1,则这个元素存在集合中,否则不存在。
因为hash、取模会有碰撞、所以会存在误差率。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。