初识BloomFilter--布隆过滤器以及Python简单代码实现

时间:2019-09-17
本文章向大家介绍初识BloomFilter--布隆过滤器以及Python简单代码实现,主要包括初识BloomFilter--布隆过滤器以及Python简单代码实现使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

用法及优缺点

BloomFilter可以解决的问题:

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

算法优缺点

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

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

原理介绍

基本原理

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

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

以上图为例,具体的操作流程:假设集合里面有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

原文地址:https://www.cnblogs.com/i-love-python/p/11537720.html