Bloom_filter

布隆过滤器介绍

基本概念:它实质上是一个很长的二进制向量和一系列随机映射函数 (Hash函数)。

作用:它是一个空间效率高的概率型数据结构,用来告诉你:一个元素一定不存在或者可能存在

优点:

  • 在存储空间和时间都是常数,即hash函数的个数
    
  • Hash 函数相互之间没有关系,方便由硬件并行实现。
    
  • 布隆过滤器不需要存储元素本身,在某些对保密要求非常严格的场合有优势。
    
  • 布隆过滤器可以表示全集,其它任何数据结构都不能。
    

缺点:

  • 有误判率存在
  • 不支持删除

适用场景:

  • 预防缓存穿透:布隆过滤器快速判断数据是否存在,避免通过查询数据库来判断数据是否存在。
  • 网络爬虫:布隆过滤器可以用来去重已经爬取过的URL。
  • 邮箱的垃圾邮件过滤。
  • 黑白名单。

原理

结构

布隆过滤器实现原理就是一个超大位数的数组(BitMap)和多个不同Hash算法函数。与寻常数组不同的是,BitMap一个数组元素占一个bit,这一特性决定了BitMap能够极大地节省空间

image-20240509090000811

添加元素

将要添加的元素分别通过k个哈希函数计算得到k个哈希值,这k个hash值对应位数组上的k个位置,然后将这k个位置设置为1。

image-20240509090026138

当不同元素在计算到相同的值后,依旧保持这一位为1即可。

image-20240509084931019

查询元素

将要查询的元素分别通过k个哈希函数计算得到k个哈希值,这k个hash值对应位数组上的k个位置。如果这k个位置中有一个位置为0,则此元素一定不存在集合中。如果这k个位置全部为1,则这个元素可能存在。

误判

需要注意的是,布隆过滤器无法确定元素存在,只能确定元素不存在。出现的原因是多个输入经过哈希之后在相同的bit位置1了,这样就无法判断究竟是哪个输入产生的,因此误判的根源在于相同的 bit 位被多次映射且置 1。

这种情况也造成了布隆过滤器的删除问题,即布隆过滤器不存在删除操作。因为布隆过滤器的每一个 bit 并不是独占的,很有可能多个元素共享了某一位。如果我们直接删除这一位的话,会影响其他的元素。

应用场景

防止缓存穿透。缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。使用布隆过滤器能够避免频繁查询不存在的数据,减轻数据库的压力。

业务场景中判断用户是否阅读过某视频或文章,比如抖音或头条,当然会导致一定的误判,但不会让用户看到重复的内容。

gun hash表, 主要是利用 Bloom Filter, 在常量时间内判断, 字符是否存在, 以及对应 .dynsym 的位置. 使用 gcc -g -o hello -Wl,--hash-style=sysv(gnu) hello.c 可以产生旧版本的 hash 表.