redis应用实战(布隆过滤器)
Posted 小马的学习笔记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis应用实战(布隆过滤器)相关的知识,希望对你有一定的参考价值。
布隆过滤器是Burton Howard Bloom在1970年提出来的,一种空间效率极高的概率型算法和数据结构,主要用来
判断一个元素是否在集合中存在。因为他是一个概率型的算法,所以会存在一定的误差,如果传入一个值去布隆过
滤器中检索,可能会出现检测存在的结果但是实际上可能是不存在的,但是肯定不会出现实际上不存在然后反馈存
在的结果。因此,Bloom Filter不适合那些“零错误”的应用场合。而在能容忍低错误率的应用场合下,Bloom Filter
通过极少的错误换取了存储空间的极大节省。
bitmap
所谓的Bit-map就是用一个bit位来标记某个元素对应的Value,通过Bit为单位来存储数据,可以大大节省存储空间.
所以我们可以通过一个int型的整数的32比特位来存储32个10进制的数字,那么这样所带来的好处是内存占用少、
效率很高(不需要比较和位移)比如我们要存储5(101)、3(11)四个数字,那么我们申请int型的内存空间,会有32
个比特位。这四个数字的二进制分别对应
从右往左开始数,比如第一个数字是5,对应的二进制数据是101, 那么从右往左数到第5位,把对应的二进制数据
存储到32个比特位上。
第一个5就是 00000000000000000000000000101000
输入3时候 00000000000000000000000000001100
布隆过滤器原理
有了对位图的理解以后,我们对布隆过滤器的原理理解就会更容易了,仍然以前面提到的40亿数据为案例,假设这
40亿数据为某邮件服务器的黑名单数据,邮件服务需要根据邮箱地址来判断当前邮箱是否属于垃圾邮件。原理如下
假设集合里面有3个元素x, y, z,哈希函数的个数为3。首先将位数组进行初始化,将里面每个位都设置位0。对于
集合里面的每一个元素,将元素依次通过3个哈希函数进行映射,每次映射都会产生一个哈希值,这个值对应位数
组上面的一个点,然后将位数组对应的位置标记为1。查询W元素是否存在集合中的时候,同样的方法将W通过哈
希映射到位数组上的3个点。如果3个点的其中有一个点不为1,则可以判断该元素一定不存在集合中。反之,如果
3个点都为1,则该元素可能存在集合中
public static void main(String[] args)
BloomFilter bloomFilter=BloomFilter.create
(Funnels.stringFunnel(Charset.defaultCharset()),1000000,0.001); //1%,有个概率问题,布隆越大,占用的空间越多,但是错误概率减小了
bloomFilter.put("ma");
System.out.println(bloomFilter.mightContain("ma"));//为true表示在布隆过滤器里
接下来按照该方法处理所有的输入对象,每个对象都可能把bitMap中一些白位置涂黑,也可能会遇到已经涂黑的
位置,遇到已经为黑的让他继续为黑即可。处理完所有的输入对象之后,在bitMap中可能已经有相当多的位置已
经被涂黑。至此,一个布隆过滤器生成完成,这个布隆过滤器代表之前所有输入对象组成的集合。
如何去判断一个元素是否存在bit array中呢? 原理是一样,根据k个哈希函数去得到的结果,如果所有的结果都是
1,表示这个元素可能(假设某个元素通过映射对应下标为4,5,6这3个点。虽然这3个点都为1,但是很明显这3
个点是不同元素经过哈希得到的位置,因此这种情况说明元素虽然不在集合中,也可能对应的都是1)存在。 如果
一旦发现其中一个比特位的元素是0,表示这个元素一定不存在
至于k个哈希函数的取值为多少,能够最大化的降低错误率(因为哈希函数越多,映射冲突会越少),这个地方就
会涉及到最优的哈希函数个数的一个算法逻辑
以上是关于redis应用实战(布隆过滤器)的主要内容,如果未能解决你的问题,请参考以下文章
硬核 | Redis 布隆(Bloom Filter)过滤器原理与实战