现在看来,将100亿个数据先存放到hashmap,然后再判断是否存在某个数,的确不是一个好方法。首先,写的性能比较低;其次,所需的内存太大。据统计,100亿个数据存入hashmap大概须要几百G的内存。
那有没有一个更好的实现办法呢?有,可以利用布隆过滤,即是本文即将先容的紧张内容。
什么叫布隆过滤布隆过滤器(英语:Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制矢量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个凑集中。它的优点是空间效率和查询韶光都远远超过一样平常的算法,缺陷是有一定的误识别率和删除困难。
布隆过滤的事理
下图表示有三个hash函数,比如一个凑集中有x,y,z三个元素,分别用三个hash函数映射到二进制序列的某些位上,假设我们判断w是否在凑集中,同样用三个hash函数来映射,结果创造取得的结果不全为1,则表示w不在凑集里面。
详细的操作流程如下:
第一步:开辟空间
开辟一个长度为m的位数组(或者称二进制向量),这个不同的措辞有不同的实现办法,乃至你可以用文件来实现。
第二步:探求hash函数
获取几个hash函数,前辈们已经发明了很多运行良好的hash函数,比如BKDRHash,JSHash,RSHash等等。这些hash函数我们直接获取就可以了。
第三步:写入数据
将所须要判断的内容经由这些hash函数打算,得到几个值,比如用3个hash函数,得到值分别是1000,2000,3000。之后设置m位数组的第1000,2000,3000位的值位二进制1。
第四步:判断
接下来就可以判断一个新的内容是不是在我们的凑集中。判断的流程和写入的流程是同等的。
布隆过滤的PHP实现由于Redis实现了setbit和getbit操作,天然适宜实现布隆过滤器,redis也有布隆过滤器插件,以是这里利用php+redis实现布隆过滤器。
首先定义一个hash函数凑集类,这些hash函数不一定都用到,实际上32位hash值的用3个就可以了,详细的数量可以根据你的位序列总量和你须要存入的量决定,上面已经给出最佳值。
接着便是连接redis来进行操作
上面定义的是一个抽象类,如果要利用,可以根据详细的业务来利用。比如下面是一个过滤重复内容的过滤器。
参考
https://blog.csdn.net/leeafay/article/details/78681534
http://imhuchao.com/1271.html