当前位置: 首页 > news >正文

10亿条URL的黑名单,如何快速判断一个新请求的URL是否在黑名单内?

在日常开发中,你是否遇到过这样的场景:

有一个包含10亿条URL的黑名单,如何快速判断一个新请求的URL是否在黑名单内,同时避免占用几十GB的内存?

在我们学习缓存三剑客时,关于缓存穿透,我们常用的解决方案之一是什么?

这些问题的核心,都是对海量数据的存在性判断,我们不需要获取数据本身,只需要知道“在”或“不在”,而布隆过滤器(Bloom Filter),就能很好地解决这个问题。

一、布隆过滤器是什么?

是一种空间高效的概率型数据结构,核心作用是快速判断一个元素是否存在于一个集合中。

布隆过滤器主要由两部分组成,

一部分是初始值都为 0 的位图数组,

一部分是N 个哈希函数。

布隆过滤器不存储数据本身,只存储数据的哈希标记。当我们往数据库中写数据时,顺便在布隆过滤器中做个标记,这样下次查数据时,只要查布隆过滤器,查的数据没有标记的话,那说明数据库里也没有。

那既然这么说了,查布隆过滤器一定很快吧?确实很快。查询布隆过滤器的时间复杂度O(k),k是哈希函数个数,通常是个位数,效率很高。

二、布隆过滤器是怎么工作的?

布隆过滤器的底层结构很简单,只有两个核心组件:

一个固定长度的位图数组(初始值都为0),

一组独立的哈希函数,

所有逻辑都围绕这两个组件展开。

接下来举个例子:

假设我有一个布隆过滤器,数组初始长度为8,哈希函数个数为3

当我们插入元素“bloom”时,步骤如下:

  1. 将“bloom”传入3个哈希函数,得到3个不同的哈希值;

  2. 然后再把这 3 个哈希值对 8 取模

  3. 将得到的结果在数组中的相应位置置1,比如取模得到1,3,5 那就1,3,5位置1 (总共0-7)

这样一通操作之后,以后当我们要查询"bloom"是否在数据库中时,只需要通过布隆过滤器查第1,3,5位置是否全为1,必须全为1才可能行,只要有一个0都说明“bloom”不在数据库中。

那为什么是可能行呢?

因为不同的数经计算得到的哈希值对8取模结果可能是一样的,可能存在哈希冲突。那这样明明数据库中没有这个数,我却算出了它1,3,5位也是1,这就判断错误了。

三、使用布隆过滤器解决缓存穿透

这里就回到了开头的缓存三剑客中的缓存穿透了。

发生缓存穿透原因是因为用户请求一个不存在的数据,此数据在缓存和数据库中都不存在。

这是我们可以用布隆过滤器存储所有已存在的key,请求过来时,先查布隆过滤器,如果返回“绝对不存在”,那就直接返回空结果,不访问缓存和数据库。如果返回“可能存在”,再查缓存和数据库。这样就能拦截99%以上的无效请求,保护数据库。

四、布隆过滤器的其它应用

1. 海量数据去重

比如爬虫去重:爬取网页时,需要记录已爬取的URL,避免重复抓取。如果用哈希表存储,1亿条URL会占用几十GB内存,而用布隆过滤器,仅需几十MB内存就能搞定,完美解决空间瓶颈。

类似场景还有:邮件黑名单去重、用户ID去重、日志去重等。

2. 数据库索引优化

HBase、LevelDB、RocksDB等数据库引擎,会用布隆过滤器判断目标键是否存在于某个SSTable文件中,避免不必要的磁盘IO操作,提升查询性能——如果布隆过滤器判断键不存在,就无需读取磁盘文件,直接返回空结果。

3. 分布式系统中的数据校验

比如分布式缓存中,判断一个key是否在其他节点的缓存中;区块链轻节点中,判断某个交易是否可能包含在区块中,减少数据同步的开销。

五、总结

布隆过滤器的本质,是“用极小的空间成本,换取极高的查询效率,同时接受轻微的误判”。它不适合所有场景,但在海量数据的存在性判断中,是无可替代的工具。

如果觉得这篇博客对你有帮助,欢迎点赞~收藏~评论~

http://www.jsqmd.com/news/820021/

相关文章:

  • 别再优化传统SEO了!2026年AI搜索排名核心因子突变——5大隐性信号(用户意图蒸馏度、上下文保真率、推理链可溯性)全曝光
  • 基于Docker的AI开发环境部署:hammercui/qmd-python-cuda镜像实战指南
  • 代码可视化工具:从AST解析到自动化图表生成的技术实践
  • 使用pretty-log美化终端日志:提升开发调试效率的实践指南
  • 2026年4月市面上评价高的封箱机供应商推荐,光纤激光机/包装袋喷码机/紫外激光机/分页机/平面贴标机,封箱机品牌选哪家 - 品牌推荐师
  • 江西VI设计品牌哪家强
  • 别再只用AddModuleScore了!用irGSEA包一站式搞定单细胞基因集富集分析与8种可视化
  • 从穿孔卡片到多任务并行:聊聊操作系统演进的几个关键“顿悟”时刻
  • AI产品开发脚手架:基于Next.js与Prisma的全栈技术栈解析
  • 基于MCP协议构建TikTok趋势分析服务器:架构设计与实战指南
  • LTX2.3 最强开源视频生成模型 文生图 / 图生视频 / 音频驱动|低端显卡本地安装
  • 刘强东把京东零售的钱,都“种”进了外卖、机器人和出海
  • 18、K8S-调度管理
  • 装机实战:Win10系统盘安装遇“找不到驱动程序”的排查与解决指南
  • 基于MCP协议构建微信通知服务:解耦业务与通知逻辑的实践
  • Magnet2Torrent技术解析:磁力链接到种子文件的工程化转换方案
  • 全域数学·体积与表面积通项定理【乖乖数学】
  • Arm Debugger内存操作与MMU调试实战指南
  • 前端学习打卡Day9:CSS 关系选择器、综合实战案例|古诗鉴赏网页制作
  • 西电B测:基于SystemView的2PSK调制解调仿真与性能分析
  • 第5篇:电力电子行业全解析:主流岗位、薪资区间与职业发展路径
  • Adafruit 9-DoF IMU模块实战:从硬件连接到姿态解算与数据融合
  • 基于MCP协议的AI智能体安全扫描器:架构、部署与实战指南
  • FPGA架构定义文件:开源工具链的芯片手册与核心数据源
  • Taotoken在高校科研项目中实现多模型API的成本可控调用
  • Flume数据采集工具深度解析与实战配置
  • 深耕UE5:放下浮躁,在虚拟世界打磨创作本心
  • 基于MCP协议集成Seedream:为AI智能体赋予图像生成能力
  • 【AI for EDA】基于 LLM 的 UPF 自动生成:从 SpecVision 到 BusForge
  • 基于RAG的代码语义搜索插件:为Cursor打造本地化智能代码助手