面试官:项目中如何实现布隆过滤器?

简介: 面试官:项目中如何实现布隆过滤器?

谈起“布隆过滤器”相信大家都不陌生,它也算日常面试中的常见面试题了。例如,当面试官在问到 Redis 模块的相关问题时,可能会问到缓存穿透(Redis 四大经典问题之一),而缓存穿透的经典解决方案之一,则是“布隆过滤器”。

但是,对于布隆过滤器是什么?以及布隆过滤器的实现原理?相信大部分同学都能回答个七七八八。当如果被问道:项目当中是如何实现布隆过滤器的?这个时候大部分同学就又回答不上来了,所以今天咱们就来探讨一下这个问题。

1. 什么是布隆过滤器?

布隆过滤器(Bloom Filter)是一种高效的数据结构,由布隆在 1970 年提出。它主要用于判断一个元素可能是否存在于集合中,其核心特性包括高效的插入和查询操作,但存在一定的假阳性(False Positives)可能性。

布隆过滤器实现如下图所示:

根据 key 值计算出它的存储位置,然后将此位置标识全部标识为 1(未存放数据的位置全部为 0),查询时也是查询对应的位置是否全部为 1,如果全部为 1,则说明数据是可能存在的,否则一定不存在

也就是说,如果布隆**过滤器**说一个元素不在集合中,那么它一定不在这个集合中;但如果它说一个元素在集合中,则有可能是不存在的(存在误差,假阳性)

2.布隆过滤器特征

  1. 高效节省空间:布隆过滤器不存储数据本身,只存储数据对应的哈希比特位,因此占用空间非常小
  2. 快速的插入和查询:插入和查询操作的时间复杂度都为 O(k),其中 k 为哈希函数的个数,这使得布隆过滤器在处理大量数据时非常高效。
  3. 存在假阳性:由于哈希碰撞的可能性,布隆过滤器在判断元素存在时可能会出现误判,即元素实际上不在集合中,但过滤器错误地认为其存在。这种误判率取决于哈希函数的个数和位数组的长度。
  4. 不支持删除操作:一旦一个元素被添加到布隆过滤器中,很难将其准确地删除。因为多个元素可能会共用位数组中的某些位,删除一个元素可能会影响其他元素的判断结果
  5. 灵活性与可配置性:布隆过滤器的误判率、位数组的长度和哈希函数的个数都是可以根据具体应用场景进行调整的,以达到最优的性能和误判率平衡。

3.使用场景

布隆过滤器的主要使用场景有以下几个:

  1. 大数据量去重:可以用布隆过滤器来进行数据去重,判断一个数据是否已经存在,避免重复插入。
  2. 防止缓存穿透问题:可以用布隆过滤器来过滤掉恶意请求或请求不存在的数据,避免对后端存储的频繁访问。
  3. 网络爬虫URL 去重:可以用布隆过滤器来判断 URL 是否已经被爬取,避免重复爬取。

4.布隆过滤器实现

实现布隆过滤器的方法有很多,可以分为以下两类:

  1. 分布式布隆过滤器
    1. 使用 Redis 4.0 之后提供的插件来实现布隆过滤器。
    2. 使用 Redisson 框架实现布隆过滤器。
  2. 单机布隆过滤器
    1. 使用 Google Guava 实现布隆过滤器。
    2. 使用 Java 自带的数据结构 BitSet 来实现布隆过滤器。
    3. 使用 Hutool 框架实现布隆过滤器。

5.项目中具体实现

在项目开发当中,如果使用的是 Redis 4.0+ 版本,我们通常会使用 Redis 布隆过滤器插件来实现布隆过滤器,以下是具体的实现步骤。

1.下载编译RedisBloom插件

git clone https://github.com/RedisLabsModules/redisbloom.git
cd redisbloom
make # 编译redisbloom

编译正常执行完,会在根目录生成一个 redisbloom.so 文件。

2.启用RedisBloom插件

重新启动 Redis 服务,并指定启动 RedisBloom 插件,具体命令如下:

redis-server redis.conf --loadmodule ./src/modules/RedisBloom-master/redisbloom.so

3.创建布隆过滤器

创建一个布隆过滤器,并设置期望插入的元素数量和误差率,在 Redis 客户端中输入以下命令:

BF.RESERVE my_bloom_filter 0.01 100000

4.添加元素到布隆过滤器

在 Redis 客户端中输入以下命令:

BF.ADD my_bloom_filter leige

5.检查元素是否存在

在 Redis 客户端中输入以下命令:

BF.EXISTS my_bloom_filter leige

课后思考

早期 Redis 版本中如何实现布隆过滤器?说说 Redisson 框架实现布隆过滤器的底层原理?

本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。

相关文章
|
4月前
|
算法
【数据结构】盘点那些经典的 [哈希面试题]【哈希切割】【位图应用】【布隆过滤器】(10)
【数据结构】盘点那些经典的 [哈希面试题]【哈希切割】【位图应用】【布隆过滤器】(10)
|
存储 缓存 算法
吊打面试官:海量数据处理利器,布隆过滤器
吊打面试官:海量数据处理利器,布隆过滤器
125 0
|
存储 数据采集 Web App开发
43.【面试宝典】面试宝典-redis缓存穿透之布隆过滤器
【面试宝典】面试宝典-redis缓存穿透之布隆过滤器
43.【面试宝典】面试宝典-redis缓存穿透之布隆过滤器
|
存储 缓存 NoSQL
面试必问:布隆过滤器(重写版)
这一篇是我重写的,之前写过一篇发现面试的时候问的问题虽然大概能解决,但是有几个点没有整理到位,所以自己给自己列出了很多面试常见的问题,准备一篇一篇去解决。本文整体思路是延续之前的那篇文章,在此基础之上添加了几个点而已。 布隆过滤器主要是在redis中问的比较多,因此像这种数据结构类的,主要是考原理以及使用场景。下面一点一点开始逐步介绍。
280 0
面试必问:布隆过滤器(重写版)
|
存储 数据库
面试官:如何在十亿个单词字典中,判断某个单词是否存在?(布隆过滤器)
如何在十亿个单词表中查找某个单词是否出现呢?答案已经给出来了,那就是使用布隆过滤器。那这个布隆过滤器是什么呢?下面就好好讲讲,方便在面试中提高你的zhuangbility。
167 0
面试官:如何在十亿个单词字典中,判断某个单词是否存在?(布隆过滤器)
|
1月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
1月前
|
Java C++
【Java基础面试十七】、Java为什么是单继承,为什么不能多继承?
这篇文章讨论了Java单继承的设计原因,指出Java不支持多继承主要是为了避免方法名冲突等混淆问题,尽管Java类不能直接继承多个父类,但可以通过接口和继承链实现类似多继承的效果。
【Java基础面试十七】、Java为什么是单继承,为什么不能多继承?
|
1月前
|
XML 存储 JSON
【IO面试题 六】、 除了Java自带的序列化之外,你还了解哪些序列化工具?
除了Java自带的序列化,常见的序列化工具还包括JSON(如jackson、gson、fastjson)、Protobuf、Thrift和Avro,各具特点,适用于不同的应用场景和性能需求。
|
1月前
|
Java
【Java基础面试三十七】、说一说Java的异常机制
这篇文章介绍了Java异常机制的三个主要方面:异常处理(使用try、catch、finally语句)、抛出异常(使用throw和throws关键字)、以及异常跟踪栈(异常传播和程序终止时的栈信息输出)。
|
1月前
|
Java
【Java基础面试三十八】、请介绍Java的异常接口
这篇文章介绍了Java的异常体系结构,主要讲述了Throwable作为异常的顶层父类,以及其子类Error和Exception的区别和处理方式。