【快速判断是否存在利器】布隆过滤器和布谷鸟过滤器

news/2025/3/14 13:18:02/文章来源:https://www.cnblogs.com/sun-10387834/p/18771897

从入门到精通:布隆过滤器和布谷鸟过滤器

在计算机科学领域,过滤器(Filter)是一种用于快速判断元素是否属于某个集合的数据结构。布隆过滤器(Bloom Filter)和布谷鸟过滤器(Cuckoo Filter)是两种常用的概率型过滤器,它们以高效的空间利用率和查询速度著称,广泛应用于缓存系统、数据库、网络爬虫等场景。

本文将带你从入门到精通,深入了解布隆过滤器和布谷鸟过滤器的原理、优缺点、应用场景以及实现细节,并基于 Spring Boot 项目提供保姆级的代码示例。


一、布隆过滤器 (Bloom Filter)

1.1 简介

布隆过滤器是由 Burton Howard Bloom 在 1970 年提出的一种空间效率很高的概率型数据结构。它利用多个哈希函数将一个元素映射到一个位数组中,用于判断一个元素是否属于某个集合。

1.2 工作原理

  1. 初始化:创建一个长度为 m 的位数组,所有位初始化为 0。
  2. 添加元素:使用 k 个独立的哈希函数将元素映射到位数组中的 k 个位置,并将这些位置置为 1。
  3. 查询元素:使用相同的 k 个哈希函数计算元素对应的 k 个位置,如果所有位置都为 1,则认为元素可能存在;如果有任何一个位置为 0,则元素一定不存在。

1.3 底层剖析

布隆过滤器的核心在于多哈希函数映射位数组存储。以下是其底层实现的关键点:

  • 哈希函数:布隆过滤器使用 k 个独立的哈希函数,每个哈希函数将输入元素映射到位数组中的一个位置。为了减少冲突,哈希函数应具有良好的均匀分布性。
  • 位数组:位数组是布隆过滤器的存储结构,每个元素通过哈希函数映射到位数组中的多个位置。位数组的长度 m 和哈希函数的数量 k 共同决定了布隆过滤器的误判率。
  • 误判率:布隆过滤器的误判率取决于位数组的长度 m、哈希函数的数量 k 以及插入的元素数量 n。误判率的计算公式为:

通过调整 m 和 k,可以控制误判率。

1.4 优缺点

优点

  • 空间效率高:布隆过滤器使用位数组存储数据,空间复杂度为 O(m)。
  • 查询速度快:查询时间复杂度为 O(k),k 为哈希函数的数量。
  • 支持动态添加:可以动态地向布隆过滤器中添加元素。

缺点

  • 存在误判率:布隆过滤器可能会出现误判,即判断一个不存在的元素为存在。
  • 不支持删除:由于多个元素可能共享同一个位,删除操作会影响其他元素的判断。

1.5 应用场景

  • 缓存系统:用于快速判断数据是否在缓存中,避免缓存穿透。
  • 数据库查询优化:用于快速判断某个键是否在数据库中,减少磁盘 I/O。
  • 网络爬虫:用于记录已访问的 URL,避免重复爬取。

1.6 Spring Boot 实现示例

以下是一个基于 Spring Boot 的布隆过滤器实现示例:

1.6.1 添加依赖

pom.xml 中添加 Guava 库依赖(Guava 提供了布隆过滤器的实现):

<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>32.1.2-jre</version>
</dependency>
1.6.2 实现布隆过滤器
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import org.springframework.stereotype.Service;import java.nio.charset.StandardCharsets;@Service
public class BloomFilterService {// 初始化布隆过滤器,预计插入 1000 个元素,误判率为 0.01private BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringFunnel(StandardCharsets.UTF_8), 1000, 0.01);/*** 添加元素到布隆过滤器*/public void add(String element) {bloomFilter.put(element);}/*** 判断元素是否可能存在*/public boolean mightContain(String element) {return bloomFilter.mightContain(element);}
}
1.6.3 测试布隆过滤器
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class BloomFilterController {@Autowiredprivate BloomFilterService bloomFilterService;@GetMapping("/add")public String addElement(@RequestParam String element) {bloomFilterService.add(element);return "Added: " + element;}@GetMapping("/check")public String checkElement(@RequestParam String element) {boolean exists = bloomFilterService.mightContain(element);return "Element " + element + " might exist: " + exists;}
}
1.6.4 运行测试

启动 Spring Boot 项目后,访问以下 URL 进行测试:

  • 添加元素:http://localhost:8080/add?element=test
  • 检查元素:http://localhost:8080/check?element=test

二、布谷鸟过滤器 (Cuckoo Filter)

2.1 简介

布谷鸟过滤器是布隆过滤器的一种改进版本,由 Bin Fan 等人在 2014 年提出。它通过使用布谷鸟哈希(Cuckoo Hashing)来解决布隆过滤器不支持删除操作的问题。

2.2 工作原理

  1. 初始化:创建一个包含多个桶的数组,每个桶可以存储多个指纹(fingerprint)。
  2. 添加元素:使用两个哈希函数计算元素的两个候选桶,并将元素的指纹存储到其中一个桶中。如果两个桶都满了,则进行“踢出”操作,将原有元素踢出并重新插入。
  3. 查询元素:使用相同的两个哈希函数计算元素的两个候选桶,并检查这两个桶中是否包含该元素的指纹。
  4. 删除元素:通过查找元素的指纹并将其从桶中删除。

2.3 底层剖析

布谷鸟过滤器的核心在于布谷鸟哈希指纹存储。以下是其底层实现的关键点:

  • 布谷鸟哈希:布谷鸟过滤器使用两个哈希函数 h1 和 h2 来计算元素的候选桶。具体来说,给定一个元素 x,它的两个候选桶分别为 h1(x) 和 h2(x)。如果其中一个桶有空位,则将元素的指纹存储到该桶中;如果两个桶都满了,则进行“踢出”操作,将原有元素踢出并重新插入。
  • 指纹:指纹是元素的哈希值的一部分,通常较短(例如 8 位)。指纹的唯一性决定了误判率。布谷鸟过滤器通过存储指纹而不是完整的元素来节省空间。
  • 误判率:布谷鸟过滤器的误判率取决于指纹的长度和桶的大小。指纹越长,误判率越低,但空间占用越大。

2.4 优缺点

优点

  • 支持删除操作:布谷鸟过滤器支持删除操作,且不会影响其他元素的判断。
  • 空间效率高:与布隆过滤器相比,布谷鸟过滤器在相同误判率下,空间利用率更高。
  • 查询速度快:查询时间复杂度为 O(1)。

缺点

  • 实现复杂:布谷鸟过滤器的实现比布隆过滤器复杂,尤其是在处理哈希冲突时。
  • 插入性能可能下降:在高负载情况下,插入操作可能会因为频繁的“踢出”操作而性能下降。

2.5 应用场景

  • 缓存系统:与布隆过滤器类似,但支持删除操作,适用于需要动态更新缓存的场景。
  • 数据库查询优化:支持删除操作,适用于需要频繁更新数据的场景。
  • 分布式系统:用于快速判断数据是否在分布式系统中存在。

2.6 Spring Boot 实现示例

以下是一个基于 Spring Boot 的布谷鸟过滤器实现示例:

2.6.1 添加依赖

pom.xml 中添加 Caffeine 依赖:

<dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>3.1.8</version>
</dependency>
2.6.2 实现布谷鸟过滤器
import com.github.benmanes.caffeine.cache.BloomFilter;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.stereotype.Service;@Service
public class CuckooFilterService {// 初始化布谷鸟过滤器,预计插入 1000 个元素,误判率为 0.01private BloomFilter<String> cuckooFilter = Caffeine.newBuilder().maximumSize(1000).buildFilter();/*** 添加元素到布谷鸟过滤器*/public void add(String element) {cuckooFilter.put(element);}/*** 判断元素是否可能存在*/public boolean mightContain(String element) {return cuckooFilter.mightContain(element);}/*** 删除元素(布谷鸟过滤器不支持直接删除,可以通过重建过滤器实现)*/public void clear() {cuckooFilter = Caffeine.newBuilder().maximumSize(1000).buildFilter();}
}
2.6.3 测试布谷鸟过滤器
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/cuckoo")
public class CuckooFilterController {@Autowiredprivate CuckooFilterService cuckooFilterService;@PostMapping("/add")public String addElement(@RequestParam String element) {cuckooFilterService.add(element);return "Added: " + element;}@GetMapping("/check")public String checkElement(@RequestParam String element) {boolean exists = cuckooFilterService.mightContain(element);return "Element " + element + " might exist: " + exists;}@DeleteMapping("/clear")public String clearFilter() {cuckooFilterService.clear();return "Filter cleared";}
}
2.6.4 运行测试

启动 Spring Boot 项目后,访问以下 URL 进行测试:

  • 添加元素:http://localhost:8080/cuckoo/add?element=test
  • 检查元素:http://localhost:8080/cuckoo/check?element=test
  • 清空过滤器:http://localhost:8080/cuckoo/clear

三、布隆过滤器 vs 布谷鸟过滤器

特性 布隆过滤器 布谷鸟过滤器
空间效率 更高
查询速度 O(k) O(1)
误判率 可控制 可控制
删除操作 不支持 支持
实现复杂度 简单 复杂
插入性能 稳定 高负载时可能下降

四、总结

布隆过滤器和布谷鸟过滤器都是高效的概率型数据结构,适用于需要快速判断元素是否属于某个集合的场景。布隆过滤器实现简单,空间效率高,但不支持删除操作;布谷鸟过滤器在支持删除操作的同时,进一步提高了空间效率,但实现复杂度较高。

在实际应用中,可以根据具体需求选择合适的过滤器。如果不需要删除操作,布隆过滤器是一个简单高效的选择;如果需要支持删除操作,布谷鸟过滤器则更为合适。


五、参考资料

  1. Bloom, B. H. (1970). Space/time trade-offs in hash coding with allowable errors. Communications of the ACM, 13(7), 422-426.
  2. Fan, B., Andersen, D. G., Kaminsky, M., & Mitzenmacher, M. (2014). Cuckoo filter: Practically better than bloom. In Proceedings of the 10th ACM International on Conference on emerging Networking Experiments and Technologies (pp. 75-88).

希望这篇博客能帮助你从入门到精通布隆过滤器和布谷鸟过滤器。如果你有任何问题或建议,欢迎在评论区留言!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/898626.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!

前言 今天大姚给大家分享 3 个 .NET 开源、免费的文件压缩处理库,希望可以快速帮助同学们实现文件压缩和解压功能! SharpCompress SharpCompress 是一个基于 C# 编写的压缩库,支持多种压缩格式的解压与部分格式的写入,专为.NET多版本设计,适合处理大文件和流式压缩。适用于…

4S店如何做好线索管理?900条线索硬刚11台成交的底层逻辑

什么是4S店的线索管理?4S店线索管理怎么做?这篇来聊聊4S店怎么管好销售线索,希望对大家有所帮助。 线索管理,说白了就是别让客户信息浪费掉,把每个潜在客户的价值榨干。但现实是,很多店要么被无效线索淹没,要么跟进不到位,最后成交率低得可怜。 所以这篇我结合行业经验…

69.9K star!这个API调试神器让你告别Postman,开源免费真香!

Hoppscotch是一款专为开发者打造的轻量级API调试工具,凭借其极简的界面设计和强大的功能支持,已成为GitHub上最受欢迎的API开发工具之一。无需安装客户端,打开浏览器即可享受媲美Postman的专业体验!嗨,大家好,我是小华同学,关注我们获得“最新、最全、最优质”开源项目和…

古生物学家与人工智能的较量

古生物学家与人工智能的较量 捍卫史前真相:人工智能如何威胁古生物学的艺术与准确性 亚历杭德罗伊斯基尔多洛佩兹,博士由Mistral Le Chat创作的人工智能恐龙。有许多错误,但最明显的就是额外的一条腿。五条腿的恐龙有人要吗? 曾经,我问过ChatGPT:人工智能取代古生物学家的…

【日记】这两天收了好多好多快递!(896 字)

正文剩下的化妆品都到了。照片打印机也到了。其实在看到 into you 这个品牌的时候,我第一反应直接直译为 “进入你”。事实证明我还是太色了,笑死。看了一下它的翻译,“心慕与你”。颇有文学作品那种乱翻译的味道(笑。此外还发现它的写法有很多种,有时候把 in 和 to 分开,…

Nginx配置文件不清楚如何重启并成功运行服务

事件起因是公司阿里云测试域名解析失败,通过与阿里云售后联系处理排查,发现是由于80和443端口不可达导致。随后联系云服务器运营商,经过简单沟通之后,即使在配置了安全组情况下,还是存在一样问题。最终问题定位是云服务器中没有对80和443端口的监听,经过分析最终的生产服…

sqlplus显示乱码如何处理

一、乱码二、查看数据库字符集 SQL> SELECT * FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER IN (NLS_CHARACTERSET, NLS_NCHAR_CHARACTERSET); PARAMETER VALUE NLS_NCHAR_CHARACTERSET AL16UTF16 NLS_CHARACTERSET AL32UTF8三、操作系统设置NLS_LANG [oracle@yeshuo ~]$ …

家风啊家风

。。。。。。。。。。。。。。。。。。。 并不是一切, 都是, 水到渠成, 自然而然, 总有总有, 那么, 点滴的咔城。 。。。。。。。。。。 在影响, 一个家庭, 一个圈子, 一个小镇, 一个县城, 一个集市, 一个国家, 一个世界。 。。。。。。 我家的风格是什么呢? 。。…

周边上新:园子的第一款马克杯温暖上架

温暖可爱的闪存星星,AI 福袋表示 AI 将给开发者带来更多的机会,另一面是3种主流编程语言与园子的网址,欢迎前往周边小店选购温暖可爱的闪存星星,AI 福袋表示 AI 将给开发者带来更多的机会,另一面是3种主流编程语言与园子的网址,欢迎前往周边小店选购 https://cnblogs.vi…

DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?

大家好,我是狂师。 前阵子在知乎闲逛时,有个问题激起了大家的热议:“DeepSeek 如何颠覆传统软件测试?测试工程师会被淘汰吗”。这看似简单的一问,激起层层思考,针对这个问题,今天简单来聊聊。 测试工程师会被淘汰吗? 我的观点十分明确:不会!但这绝非无条件成立,它有…

创建一个job类库,运行项目出现异常“使用顶级语句的程序必须是可执行文件”

异常: 此项目的入口使用顶级语句的方式非Main函数 此时需要将项目的输出类型设置为可行文件类型(OutputType) 关于顶级语句参考

汉字和英文字符对齐研究

1. Windows记事本的情况 2. VS Code 的情况 3. VS 2022的情况 和记事本一样, 不再贴图。4. 总结 1) 不同的编辑器,不同的字体,情况不一样2) 中文和英文,需要不同的个数,才能完全对齐 3) 如果中英文字符数,不能达到上面的字数的倍数,无法对齐 4) 对于强迫症,可以通…