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

一次推荐系统的性能瓶颈:为什么很多工程团队最终都会用上 Bloom Filter

在很多技术讨论里,性能问题往往被归结为算法复杂度。但在真实系统中,拖慢服务的常常不是复杂计算,而是那些被重复执行的简单判断。

例如推荐系统里一个看似普通的需求:不要再给用户推荐他已经看过的内容。

听起来非常简单。但当系统规模上来之后,这件事很快会变成一个真正的工程问题。

      当推荐系统进入高并发阶段

设想一个内容推荐服务。

系统每秒需要处理大约 1.8 万次请求,每个请求需要从候选池里评估大约 100 多篇内容。仅这一项,就意味着系统每秒要做超过 200 万次“是否看过”的判断。

最直观的做法,是把用户历史行为存在数据库或缓存里,然后逐条查询。

问题很快出现:

如果每次都访问存储系统,数据库或 Redis 很容易成为瓶颈;如果把完整历史放进内存,又会消耗大量资源。

于是工程团队开始问一个更现实的问题:

有没有一种方法,可以在极低成本下快速判断“这个内容大概率没看过”?

Bloom Filter 就是在这种场景下进入系统设计的。

      Bloom Filter 为什么在工程里这么受欢迎

Bloom Filter 的核心作用只有一个:

判断一个元素是否“可能存在”。

它的特点非常明确:

  • 不会出现假阴性(如果说不存在,那一定不存在)
  • 可能出现假阳性(有时会误判为存在)

从理论角度看,这似乎是个缺点。但在工程里,它恰恰是一种可以接受的交易。

回到推荐系统的例子。

如果 Bloom Filter 误判某篇文章“用户已经看过”,结果只是这篇内容没有被推荐而已。用户几乎不会察觉。

但如果不用 Bloom Filter,每个候选内容都要访问存储系统,那么系统成本会迅速上升。

换句话说:

工程团队用一点点“可能错过推荐”的概率,换来了系统吞吐量的大幅提升。

这就是典型的工程权衡。

      真正的关键:参数怎么选

很多介绍 Bloom Filter 的文章会停在算法原理,但在真实系统里,决定效果的往往是参数选择。

两个参数最重要:

  • 位数组大小(m)
  • 哈希函数数量(k)

这两个值直接决定三个指标:

  • 内存占用
  • 插入速度
  • 误判率

如果数组太小,误判率会迅速上升;如果数组太大,内存优势就会消失。

工程上通常会先确定可接受的误判率,例如 1% 或 0.1%,然后根据预计元素数量反推 Bloom Filter 的大小。

很多团队第一次上线 Bloom Filter 时会忽略一个问题:

元素数量会增长。

当过滤器逐渐接近容量上限时,误判率会明显上升。因此在长期运行的系统中,通常需要:

  • 定期重建
  • 分片 Bloom Filter
  • 或使用可扩展版本

这些都是实际系统里必须考虑的事情。

      为什么很多团队用 Go 来实现

Bloom Filter 的实现并不复杂,但它涉及大量位操作和哈希计算。

Go 在这里有几个明显优势:

第一,内存模型简单。

位数组可以直接用 byte slice 表示,读写成本非常低。

第二,性能稳定。

Go 的并发模型允许在高并发服务中安全使用共享结构。

第三,部署简单。

很多推荐服务本身就是 Go 编写的微服务,把 Bloom Filter 直接嵌入服务进程可以减少额外网络调用。

典型实现结构非常清晰:

  • 一个位数组
  • 一组哈希函数
  • Add 与 Test 两个操作

插入时设置多个 bit,查询时检查这些 bit 是否全部为 1。

逻辑简单,但在大规模请求下可以节省大量存储访问。

      Bloom Filter 不是万能解

虽然它很高效,但并不是所有场景都适合。

以下几种情况通常不适合:

如果误判成本极高,例如金融交易或权限系统,那么概率型结构就不合适。

如果数据量很小,用普通 HashSet 反而更简单。

如果系统必须支持删除操作,标准 Bloom Filter 也无法直接做到,需要使用 Counting Bloom Filter 等变种。

因此工程团队真正需要回答的不是“这个结构厉不厉害”,而是:

误判带来的业务代价是否可以接受。

只要这个问题的答案是“可以”,Bloom Filter 往往就是一个非常划算的方案。

      一条典型的落地路径

很多团队最终都会以类似方式引入 Bloom Filter:

第一步,在服务层加入过滤器作为预检查。

先判断内容是否可能出现过,如果结果是“肯定没有”,就直接跳过数据库查询。

第二步,监控误判率。

通过日志统计 Bloom Filter 拦截率和真实命中率,确认参数是否合理。

第三步,规划扩展策略。

随着用户行为增长,提前准备新的过滤器或分片结构,避免误判率失控。

当这套机制稳定之后,系统会得到一个很直接的收益:

数据库访问量显著下降,而推荐服务的吞吐能力明显提升。

很多工程优化看起来是算法问题,本质却是系统成本问题。

Bloom Filter 的价值就在这里——

它不是让系统更聪明,而是让系统在大规模运行时更便宜。

 

声明

关注微信公众号解锁更多技术资讯,感谢您的支持!

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

相关文章:

  • GD32F4系列定时器正交译码器实战:用编码器测电机转速(附CubeMX配置)
  • Apple-Mobile-Drivers-Installer:革新性极简驱动解决方案,1分钟解决iPhone USB网络共享难题
  • 从零开始搞工业质检模型?试试用ModelArts的‘主动学习’模式,能省70%标注预算
  • 多平台直播录制解决方案:StreamCap实战指南
  • 百度网盘提取码智能获取工具:让资源获取效率提升90%的实用解决方案
  • 【深度解析】红枣原液超滤工艺:核心优势、保存与保质期 - 速递信息
  • 高效处理闲置卡片:加油卡回收的全流程解析 - 团团收购物卡回收
  • 深入探索Selenium DevTools:解锁浏览器自动化新境界
  • 分析管家婆财务软件实力情况,在武威靠谱吗 - mypinpai
  • 多模态Agent:GLM-ASR语音交互集成实战
  • 如何通过OpenCore Legacy Patcher让老旧Mac焕发新生:3个步骤实现系统升级自由
  • 美团闪购有哪些自营品牌?周年庆福利拉满,速领1515元券包嗨购 - 资讯焦点
  • VS 中查看重载方法的 Ctrl + Shift + Space快捷键失效
  • instruction-tuning后Rouge提升4.2:LLM效果评估
  • 普中PZ6808L-F4开发板4.3寸TFTLCD显示BMP图片的完整流程(附Image2Lcd配置与避坑点)
  • 美团闪购周年庆有什么优惠?全方位攻略+福利拆解 - 资讯焦点
  • 2026黔南硅PU球场材料怎么联系?找靠谱供应商电话避免被坑 - 精选优质企业推荐榜
  • 大模型应用开发第一课:从Prompt到Function Calling
  • 聊聊好用的电商云仓服务公司,上海地区性价比如何 - 工业品牌热点
  • 高效处理NCM文件:ncmdumpGUI开源工具使用指南
  • runner = unittest.TextTestRunner(verbosity=2) verbosity=2是什么意思?
  • Electron应用打包后还能改配置?巧用Node.js fs模块实现动态API管理
  • Xilinx FPGA PCIe硬核配置实战:从Base到Advanced模式详解
  • 长期染发,不伤身体的染发膏推荐2026 - 品牌排行榜
  • 聊聊电商云仓服务推荐哪家,祥复瑞口碑如何 - myqiye
  • SDMatte抠图质量评估:基于SAD、Grad、Conn指标的客观性能分析报告
  • Selenium爬虫实战:5分钟搞定京东商品数据抓取(附完整代码)
  • Ubuntu下Synopsys EDA七件套安装避坑指南:从虚拟机配置到license报错解决
  • 3个技巧掌握B站4K视频本地化:bilibili-downloader全攻略
  • VALORANT dll文件损坏官方修复方法:0xc000007b与无法定位输入点全搞定