布隆过滤器

238 阅读2分钟

简洁理解

直观的说,bloom算法类似一个hash set,用来判断某个元素(key)是否在某个集合中。和一般的hash set不同的是,这个算法无需存储key的值,对于每个key,只需要k个比特位,每个存储一个标志,用来判断key是否在集合中。

算法过程

数组的每个元素都只占1bit空间,并且每个元素只能为0或1。

布隆过滤器还拥有k个哈希函数,当一个元素加入布隆过滤器时,会使用k个哈希函数对其进行k次计算,得到k个哈希值,并且根据得到的哈希值,在维数组中把对应下标的值置位1。

image.png 判断某个数是否在布隆过滤器中,就对该元素进行k次哈希计算,得到的值在位数组中判断每个元素是否都为1,如果每个元素都为1,就说明这个值在布隆过滤器中。

优缺点

优点

不需要存储key,节省空间

缺点

    1. 算法判断key在集合中时,有一定的概率key其实不在集合中
    1. 无法删除

python实现布隆过滤器

from bitarray import bitarray
import mmh3

class BloomFilter:
    """
    Bloom Filter implemented in Python
    """
    def __init__(self, n, p):
        """
        :param n: Size of bit array 
        :param p: False positive probability
        """
        self.n = n
        self.p = p
        self.bit_array = bitarray(self.n)
        self.bit_array.setall(0)
        # Number of hash functions
        self.k = self.get_k(n, p)

    def add(self, item):
        """
        Adds an item to the bloom filter
        """
        for i in range(self.k):
            hash_value = mmh3.hash(item, i) % self.n
            self.bit_array[hash_value] = True

    def check(self, item):
        """
        Checks if an item is present in the bloom filter
        """
        for i in range(self.k):
            hash_value = mmh3.hash(item, i) % self.n
            if self.bit_array[hash_value] == False:
                return False
        return True

    def get_k(self, n, p):
        """
        Returns the number of hash functions needed
        to achieve the required false positive probability
        """
        k = (n * math.log(2)) / math.log(1/p)
        return int(k)


bloom = BloomFilter(100000, 0.01)  # 1% error rate
bloom.add("hello")
bloom.add("world")
bloom.check("hello")   # Returns True
bloom.check("no")      # Returns False

应用案例

  • 爬虫使用redis去重
  • 缓存系统:使用布隆过滤器判断查询是否在缓存当中
  • 垃圾邮件过滤:通过布隆过滤器判断邮件是否在垃圾邮件列表当中,从而过滤垃圾邮件
  • 黑名单过滤: 判断ip/手机号是否存在黑名单当中,从而组织恶意请求