如网页 URL 去重、垃圾邮件识别、大集合中重复元素的判断和缓存穿透等问题。
布隆过滤器是一个比特向量或者比特数组,它本质上是一种概率型数据结构,用来查找一个元素是否在 集合中,支持高效插入和查询某条记录。常作为针对超大数据量下高效查找数据的一种方法。
原理
用k个哈希函数将value转换为k个位,同时在位列表记录。
布隆过滤器可以检查值是 “可能在集合中” 还是 “绝对不在集合中” 。“可能” 表示有一定的概率,也就是说可能存在一定为误判率。
对于检查新的value是否存在过,直接查看对应的k个位是否已置位,任意一个未置位,则不存在,全部置位,则可能存在
应用
在实际工作中,布隆过滤器常见的应用场景如下:
- 网页爬虫对 URL 去重,避免爬取相同的 URL 地址;
- 反垃圾邮件,从数十亿个垃圾邮件列表中判断某邮箱是否垃圾邮箱;
- Google Chrome 使用布隆过滤器识别恶意 URL;
- Medium 使用布隆过滤器避免推荐给用户已经读过的文章;
- Google BigTable,Apache HBbase 和 Apache Cassandra 使用布隆过滤器减少对不存在的行和列的查找。 除了上述的应用场景之外,布隆过滤器还有一个应用场景就是解决缓存穿透的问题。所谓的缓存穿透就是服务调用方每次都是查询不在缓存中的数据,这样每次服务调用都会到数据库中进行查询,如果这类请求比较多的话,就会导致数据库压力增大,这样缓存就失去了意义。
利用布隆过滤器我们可以预先把数据查询的主键,比如用户 ID 或文章 ID 缓存到过滤器中。当根据 ID 进行数据查询的时候,我们先判断该 ID 是否存在,若存在的话,则进行下一步处理。若不存在的话,直接返回,这样就不会触发后续的数据库查询。需要注意的是缓存穿透不能完全解决,我们只能将其控制在一个可以容忍的范围内。(判断数据库是否有信息)
用缓存做布隆过滤器(判断缓存是否有信息)
布隆过滤器哈希函数个数k的选取
布隆过滤器k个哈希与单个哈希相比,其实就是k个哈希对误判率影响的取舍,
假设布隆过滤器有m个bit,已插入的value有n个,结论是冲突最小时 k ≈ 0.7 m / n
m越大,n越小,k就应该越大
因为n/m很小时,k=1时只需一次哈希冲突即可,而k=n时需要n次哈希冲突,k越大误判率越小
n/m很大时,k越大1的覆盖率越大,k越小误判率越小
支持删除操作吗
目前布隆过滤器只支持插入和查找操作,不支持删除操作,如果要支持删除,就要使用计数变量,每次将相应的位置为1则计数加一,删除则减一。