布隆过滤器BloomFilter原理剖析
来源:互联网 发布:淘宝网浅秋女羊毛衫 编辑:程序博客网 时间:2024/06/06 19:20
场景:
不安全网页的黑名单包含100亿个黑名单网页,每个网页URL最多占用64B。现在设计系统根据网页URL判断该网页是否在黑名单上。
要求:该系统允许万分之一以下的判断失误率,且使用的额外空间不要超过30GB。
分析:如果单纯通过数据库或者哈希表来保存下来,需要640G的空间,不满足要求。
遇到网页黑名单系统、垃圾邮件过滤系统、爬虫的网址判重系统、两份URL文件的重复URL等场景,又看到系统容忍一定程度的失误率,但是对空间要求比较严格,那么可以采取布隆过滤器来解决。
一个布隆过滤器精确地代表一个集合,并可以精确判断一个元素是否在集合中,优势在于使用很少的空间就能将准确率做到很高的程度。
布隆过滤器的原理分析:
一个URL经过K个哈希函数计算,结果相互独立,对计算出来的每个结果都对m取余,然后在长度为m的bit类型数组上把相应的位置设置为1(涂黑)。
检查过程:
一个URL经过上述过程后,得到k个在[0,m-1]范围上的值。
如果有一个不为1(不为黑),则该URL肯定不在这个集合里。
如果都是1(均被涂黑),则该URL在这个集合里面,但是可能会出现误判。(输入对象过多,但是bitMap长度过小,导致bitMap绝大部分都被涂黑,可能出现误判)
布隆过滤器的设计:
输入个数n和允许失误率----------过滤器大小m和哈希函数个数k(具体推导公式和证明看左程云《程序员代码面试指南》P303)
布隆过滤器会有误报,针对于已经发现的误报样本可以通过建立白名单来防止误报。
下面是一个具体布隆过滤器的代码实现。(不是上述题目)
假设采取k=8个散列函数,m=1<<22 长度的bitMap数组,判断字符串是否在出现在文件中。
import java.util.BitSet;import java.io.*;/** * Created by flh on 2017/8/28. */public class BloomFilter { //DEFAULT_SIZE为2的22次方,即此处的1左移22位 private static final int DEFAULT_SIZE = 1<<22; /* * 不同哈希函数的种子,一般取质数 * seeds数组共有8个值,则代表采用8种不同的哈希函数 */ private int[] seeds = new int[]{3, 5, 7, 11, 13, 31, 37, 61}; /* * 初始化一个给定大小的位集 * BitSet实际是由“二进制位”构成的一个Vector。 * 假如希望高效率地保存大量“开-关”信息,就应使用BitSet. */ private BitSet bitSets = new BitSet(DEFAULT_SIZE); //构建hash函数对象 private SimpleHash[] hashFuns = new SimpleHash[seeds.length]; //布隆过滤器配置文件存放路径 private String path = ""; public BloomFilter(String path){ /** * 给出所有的hash值,共计seeds.length个hash值。共8位。 * 通过调用SimpleHash.hash(),可以得到根据8种hash函数计算得出hash值。 * 传入DEFAULT_SIZE(最终字符串的长度),seeds[i](一个指定的质数)即可得到需要的那个hash值的位置。 */ for(int i=0; i<seeds.length; i++){ hashFuns[i] = new SimpleHash(DEFAULT_SIZE, seeds[i]); } //配置文件路径地址 this.path = path; } /** * * 方法名:add * 描述:将给定的字符串标记到bitSets中,即设置字符串的8个函数值的位置为1 * @param value */ public synchronized void add(String value){ for(SimpleHash hashFun : hashFuns){ bitSets.set(hashFun.hash(value), true); } } /** * * 方法名:isExit * 描述:判断给定的字符串是否已经存在在bloofilter中,如果存在返回true,不存在返回false * @param value * @return */ public synchronized boolean isExit(String value){ //判断传入的值是否为null if(null == value){ return false; } for(SimpleHash hashFun : hashFuns){ if(!bitSets.get(hashFun.hash(value))){ //如果判断8个hash函数值中有一个位置不存在即可判断为不存在Bloofilter中 return false; } } return true; } /** * * 方法名:init * 描述:读取配置文件 */ public void init(){ File file = new File(path); FileInputStream in = null; try { in = new FileInputStream(file); read(in); }catch(Exception e){ e.printStackTrace(); }finally{ try { if(in!=null){ in.close(); in = null; } } catch (IOException e) { e.printStackTrace(); } } } /** * * 方法名:read * 描述:根据传入的流,初始化bloomfilter * @param in */ private void read(InputStream in){ if(null == in){ //如果in为null,则返回 return; } InputStreamReader reader = null; try { //创建输入流 reader = new InputStreamReader(in, "UTF-8"); BufferedReader buffReader = new BufferedReader(reader, 512); String theWord = null; do { theWord = buffReader.readLine(); //如果theWord不为null和空,则加入Bloomfilter中 if(theWord!=null && !theWord.trim().equals("")){ add(theWord); } } while (theWord != null); } catch (IOException e){ e.printStackTrace(); } finally{ //关闭流 try { if(reader != null){ reader.close(); reader = null; } if(in != null){ in.close(); in = null; } } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { BloomFilter bloomFilterTest = new BloomFilter("e:/test.txt"); bloomFilterTest.init(); System.out.println(bloomFilterTest.isExit("spark")); System.out.println(bloomFilterTest.isExit("Storm")); } public static class SimpleHash { /* * cap为DEFAULT_SIZE,即用于结果的最大字符串的值 * seed为计算hash值的一个key值,具体对应上文中的seeds数组 */ private int cap; private int seed; public SimpleHash(int cap, int seed){ this.cap = cap; this.seed = seed; } /** * * 方法名:hash * 描述:计算hash的函数,用户可以选择其他更好的hash函数 * @param value * @return */ public int hash(String value){ int result = 0; int length = value.length(); for(int i=0; i<length; i++){ result = seed*result + value.charAt(i); } return (cap-1) & result; } }}
假如文本文件test.txt文件中内容如下:
spark1helpStorm
输出结果为:
falsetrue
- 布隆过滤器BloomFilter原理剖析
- BloomFilter(布隆过滤器)
- BloomFilter布隆过滤器
- 布隆过滤器【BloomFilter】
- /*****/BloomFilter(布隆过滤器)
- BloomFilter(布隆过滤器)原理和python支持库
- BloomFilter(布隆过滤器)
- 布隆过滤器(BloomFilter)
- 布隆过滤器简介bloomFilter
- BloomFilter布隆过滤器使用
- 布隆过滤器(BloomFilter)
- 布隆过滤器 布隆算法 BloomFilter
- Java版本的BloomFilter (布隆过滤器)
- 布隆过滤器,数据处理的神来之笔!BloomFilter
- Hbase 布隆过滤器BloomFilter介绍
- Hbase 布隆过滤器BloomFilter介绍
- Hbase 布隆过滤器BloomFilter介绍
- Hbase 布隆过滤器BloomFilter介绍
- linux C 学习笔记(二):底层文件访问
- HTMLParser
- Google Brain大牛Jeff dean视频
- 剑指offer(21)—栈的压入、弹出序列
- cannot find -lcaffe 解决
- 布隆过滤器BloomFilter原理剖析
- easyui tree 去掉默认图标,使用fontawesome
- Java线程面试题 Top 50
- 文本分析-预处理:Python文本分析工具NLTK
- SpringMVC中添加HTML等页面视图
- CSS position
- Spring事务配置的五种方式
- [JVM]Java内存模型
- MSTP实现过程