zoukankan      html  css  js  c++  java
  • 初识BloomFilter--布隆过滤器以及Python简单代码实现

    用法及优缺点

    BloomFilter可以解决的问题:

    1.字处理软件中,需要检查一个英语单词是否拼写正确
    2.在 FBI,一个嫌疑人的名字是否已经在嫌疑名单上
    3.在网络爬虫里,一个网址是否被访问过
    4.yahoo, gmail等邮箱垃圾邮件过滤功能
    5.可以用来防止缓存击穿

    算法优缺点

    算法优点:
    数据空间小,不用存储数据本身。

    算法本身缺点:
    匹配失败能确定“绝对不在集合中”,并不能保证匹配成功的值已经在集合中。
    元素可以添加到集合中,但不能被删除。
    当集合快满时,即接近预估最大容量时,误报的概率会变大。
    数据占用空间放大。一般来说,对于1%的误报概率,每个元素少于10比特,与集合中的元素的大小或数量无关。 查询过程变慢,hash函数增多,导致每次匹配过程,需要查找多个位(hash个数)来确认是否存在。

    原理介绍

    基本原理

    布隆过滤器是一个判断集合中是否包含特定元素的算法,他无需存储数据本身。
    布隆过滤器(Bloom Filter)的核心实现是一个超大的位数组和几个哈希函数。

    假设位数组的长度为m,哈希函数的个数为k,首先将位数组进行初始化,将里面每个位都设置位0。
    通过哈希将输入的字符串映射到数据的下标,然后把下标对应的值置为1,第二次相同字符串进行计算时也会被哈希函数映射到相同的下标 则可以判断匹配内容是否已经存在。

    image.png

    以上图为例,具体的操作流程:假设集合里面有3个元素{x, y, z},哈希函数的个数为3。对于集合里面的每一个元素,将元素依次通过3个哈希函数进行映射,每次映射都会产生一个哈希值,这个值对应位数组上面的一个点,然后将位数组对应的位置标记为1。查询W元素是否存在集合中的时候,同样的方法将W通过哈希映射到位数组上的3个点。如果3个点的其中有一个点不为1,则可以判断该元素一定不存在集合中。反之,如果3个点都为1,则该元素可能存在集合中。注意:此处不能判断该元素是否一定存在集合中,可能存在一定的误判率。可以从图中可以看到:假设某个元素通过映射对应下标为4,5,6这3个点。虽然这3个点都为1,但是很明显这3个点是不同元素经过哈希得到的位置,因此这种情况说明元素虽然不在集合中,也可能对应的都是1,这是误判率存在的原因。

    python简单实例实现

    如下仅为python代码实现的BloomFilter实例。真正的BloomFilter实现需要根据初始化的位数组长度决定哈希函数的个数,也有一个复杂的hash过程。

    #_*_coding:utf_8_
    import BitVector
    import os
    import sys
     
    class SimpleHash():  
        
        def __init__(self, cap, seed):
            self.cap = cap
            self.seed = seed
        
        def hash(self, value):
            ret = 0
            for i in range(len(value)):
                #加权求和
                ret += self.seed*ret + ord(value[i])
            #位运算保证最后的值在0到self.cap之间
            return (self.cap-1) & ret    
     
    class BloomFilter():
        
        def __init__(self, BIT_SIZE=1<<25):
            self.BIT_SIZE = 1 << 25
            self.seeds = [5, 7, 11, 13, 31, 37, 61]
            self.bitset = BitVector.BitVector(size=self.BIT_SIZE)
            self.hashFunc = []
            
            for i in range(len(self.seeds)):
                self.hashFunc.append(SimpleHash(self.BIT_SIZE, self.seeds[i]))
            print(self.hashFunc)
            
        def insert(self, value):
            for f in self.hashFunc:
                loc = f.hash(value)
                self.bitset[loc] = 1
            print(self.bitset)
    
        def is_contaions(self, value):
            if value == None:
                return False
            ret = True
            for f in self.hashFunc:
                loc = f.hash(value)
                ret = ret & self.bitset[loc]
            return ret
    

    文章内容部分引用:
    布隆过滤器实战【防止缓存击穿】
    http://blog.itpub.net/31561269/viewspace-2639083/
    详解,包括错误率计算
    https://blog.csdn.net/liangbopirates/article/details/8741367

    https://blog.csdn.net/demon24/article/details/8537665

  • 相关阅读:
    FxCopCmd.exe 返回错误代码 65[翻译]
    关于VS2005安装项目制作的三个参考文章链接
    Windows服务开发的四个小经验
    ThreadLocal详解
    java修饰符详解
    聚合、组合、关联、继承之间的区别【转】
    centos单用户模式修改ROOT密码
    vim的配置
    spring注解详解
    centOS修改文本界面分辨率
  • 原文地址:https://www.cnblogs.com/i-love-python/p/11537720.html
Copyright © 2011-2022 走看看