内容参考:https://www.jianshu.com/p/2104d11ee0a2java
一、数据结构
布隆过滤器是一个BIT数组,本质上是一个数据,因此能够根据下标快速找数据linux
二、哈希映射
一、布隆须要记录见过的数据,这里的记录须要经过hash函数对数据进行hash操做,获得数组下标并存储在BIT 数组里记为1。这样的记录一个数据只占用1BIT空间git
二、判断是否存在时:给布隆过滤器一个数据,进行hash获得下标,从BIT数组里取数据若是是1 则说明数据存在,若是是0 说明不存在github
三、精确度
hash算法存在碰撞的可能,因此不一样的数据可能hash为一个下标数据,故为了提升精确度就须要 使用多个hash 算法标记一个数据,和增大BIT数组的大小redis
也是由于如此,布隆过滤器判断为【数据存在】 可能数据并不存在,可是若是判断为【数据不存在】那么数据就必定是不存在的。算法
四、例子
下图映射 baidu字样到布隆过滤器中,用了三个不一样的hash函数 3BIT 判断一个数据,BIT数组大小为8数组
哈希函数返回 一、四、7服务器
咱们如今再存一个值 “tencent”,若是哈希函数返回 三、四、8 的话,图继续变为:函数
如下 4 位置发生了hash碰撞
五、如何选择哈希函数个数和布隆过滤器长度
显然,太小的布隆过滤器很快全部的 bit 位均为 1,那么查询任何值都会返回“可能存在”,起不到过滤的目的了。布隆过滤器的长度会直接影响误报率,布隆过滤器越长其误报率越小。
另外,哈希函数的个数也须要权衡,个数越多则布隆过滤器 bit 位置位 1 的速度越快,且布隆过滤器的效率越低;可是若是太少的话,那咱们的误报率会变高。
k 为哈希函数个数,m 为布隆过滤器长度,n 为插入的元素个数,p 为误报率。
六、不支持删除
布隆过滤器只能插入数据判断是否存在,不能删除,并且只能保证【不存在】判断绝对准确
以上不难看出若是给数组的每一个BIT位上加一个计数器,插入的时候+1 删除的时候 –1 就能够实现删除。
可是加计数器的实现是有问题的:
因为hash碰撞问题,布隆过滤器不能准确判断数据是否存在,就不能随意删除。其次计数器的回绕问题也须要考虑。
一、下载:
地址:https://github.com/RedisBloom/RedisBloom
下载ZIP 文件,上传到linux
RedisBloom-master.zip
二、解压编译
命令:
unzip RedisBloom-master.zip
cd RedisBloom-master
make
扫行完以上命令 后文件夹内生成一个文件名为:redisbloom.so
三、启动redis 时加载该模块
命令:
redis-server redis-6381.conf --loadmodule /zjl/software/RedisBloom-master/redisbloom.so
一、连接redis
命令:
redis-cli –a zjl123
二、测试布隆过滤
命令:
bf.add zjl 123
bf.exists zjl 123 #返回 1 ,说明存在值
bf.exists zjl 321 #返回 0, 说明不存在该值
三、准确率
Redis中有一个命令能够来设置布隆过滤器的准确率:
bf.reserve zjl 0.01 100
bf.reserve 有三个参数,分别是 key, error_rate 和 initial_size 。
错误率越低,须要的空间越大。
initial_size 参数表示预计放 入的元素数量,当实际数量超出这个数值时,误判率会上升。
因此须要提早设置一个较大的数值避免超出致使误判率升高。
若是不使用 bf.reserve,默认的 error_rate 是 0.01,默认的 initial_size 是 100。
布隆过滤器的 initial_size 估计的过大,会浪费存储空间,估计的太小,就会 影响准确率,
用户在使用以前必定要尽量地精确估计好元素数量,还须要加上 必定的冗余空间以免实际元素可能会意外高出估计值不少。
布隆过滤器的 error_rate 越小,须要的存储空间就越大,对于不须要过于精确 的场合, error_rate 设置稍大一点也无伤大雅。
好比在新闻去重上而言,误判 率高一点只会让小部分文章不能让合适的人看到,
文章的总体阅读量不会由于这 点误判率就带来巨大的改变。
一、redis布隆过滤器
没有找到jedis 支持bloom过滤器 命令的版本,只找到了另一个JAR包的支持,可是也不太好用,没弄明白如何添加密码链接
引入包
<dependency> <groupId>com.redislabs</groupId> <artifactId>jrebloom</artifactId> <version>1.0.2</version> </dependency>JAR包里只有三个类,对链接方式 和 数据类型 的支持都不够
代码:
Client client = new Client(redisProperties.getHost(), redisProperties.getPort(), 10000, 100); client.add("zjl", "123"); boolean zjl = client.exists("zjl", "123"); System.out.println(zjl);二、Guava中的BloomFilter
google的guava包中提供了BloomFilter类,直接用的是服务器内存
导入包
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>22.0</version> </dependency>代码:
private static int size = 1000000; private static BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()), size, 0.0001); public void test2() { String aa = "zjl"; bloomFilter.put(aa); System.out.println(bloomFilter.mightContain(aa)); }三、自已实现布隆过滤器
java 有bitSet数组,hash函数能够本身手动实现
本身手写是能够实现布隆过滤器的,在此不作研究。