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

redis高级数据结构布隆过滤器

文章目录

  • 背景
  • 什么是布隆过滤器
  • Redis 中的布隆过滤器
  • 布隆过滤器使用
  • 注意事项
  • 实现原理
  • 空间占用估计

背景

我们在使用新闻客户端看新闻时,它会给我们不停地推荐新的内容,它每次推荐时要去重,去掉那些已经看过的内容。问题来了,新闻客户端推荐系统如何实现推送去重的?

你会想到服务器记录了用户看过的所有历史记录,当推荐系统推荐新闻时会从每个用户的历史记录里进行筛选,过滤掉那些已经存在的记录。问题是当用户量很大,每个用户看过的新闻又很多的情况下,这种方式,推荐系统的去重工作在性能上跟的上么?

实际上,如果历史记录存储在关系数据库里,去重就需要频繁地对数据库进行 exists 查询,当系统并发量很高时,数据库是很难扛住压力的。你可能又想到了缓存,但是如此多的历史记录全部缓存起来,那得浪费多大存储空间啊?而且这个存储空间是随着时间线性增长,你撑得住一个月,你能撑得住几年么?但是不缓存的话,性能又跟不上,这该怎么办?这时,布隆过滤器 (Bloom Filter) 闪亮登场了,它就是专门用来解决这种去重问题的。它在起到去重的同时,在空间上还能节省 90% 以上,只是稍微有那么点不精确,也就是有一定的误判概率。

什么是布隆过滤器

布隆过滤器可以理解为一个不怎么精确的 set 结构,当你使用它的 contains 方法判断某个对象是否存在时,它可能会误判。但是布隆过滤器也不是特别不精确,只要参数设置的合理,它的精确度可以控制的相对足够精确,只会有小小的误判概率

当布隆过滤器说某个值存在时,这个值可能不存在;当它说不存在时,那就肯定不存
。这来源于它的底层实现,在接下来讲解原理时你就明白了。

Redis 中的布隆过滤器

Redis 官方提供的布隆过滤器到了 Redis 4.0 提供了插件功能之后才正式登场。布隆过滤器作为一个插件加载到 Redis Server 中,给 Redis 提供了强大的布隆去重功能。

布隆过滤器使用

布隆过滤器有二个基本指令, bf.add 添加元素, bf.exists 查询元素是否存在,它的用法和 set 集合的 sadd 和 sismember 差不多。注意 bf.add 只能一次添加一个元素,如果想要一次添加多个,就需要用到 bf.madd 指令。同样如果需要一次查询多个元素是否存在,就需要用到 bf.mexists 指令。

注意事项

创建布隆过滤器时需要3个参数,分别是 key, error_rate 和 initial_size。错误率越低,需要的空间越大。 initial_size 参数表示预计放入的元素数量,当实际数量超出这个数值时,误判率会上升。

所以需要提前设置一个较大的数值避免超出导致误判率升高。如果不使用 bf.reserve,默认的 error_rate 是 0.01,默认的 initial_size 是 100。

布隆过滤器的 initial_size 估计的过大,会浪费存储空间,估计的过小,就会影响准确
率,用户在使用之前一定要尽可能地精确估计好元素数量,还需要加上一定的冗余空间以避免实际元素可能会意外高出估计值很多。

布隆过滤器的 error_rate 越小,需要的存储空间就越大,对于不需要过于精确的场合,error_rate 设置稍大一点也无伤大雅。比如在新闻去重上而言,误判率高一点只会让小部分文章不能让合适的人看到,文章的整体阅读量不会因为这点误判率就带来巨大的改变。

实现原理

如下是一张布隆过滤器的结构图:
在这里插入图片描述

每个布隆过滤器对应到 Redis 的数据结构里面就是一个大型的位数组和几个不一样的无偏 hash 函数。所谓无偏就是能够把元素的 hash 值算得比较均匀。

向布隆过滤器中添加 key 时,会使用多个 hash 函数对 key 进行 hash 运算得一个整数索引值然后对位数组长度进行取模运算得到一个位置,每个 hash 函数都会算得一个不同的位置。再把位数组的这几个位置都置为 1 就完成了 add 操作。

向布隆过滤器询问 key 是否存在时,跟 add 一样,也会把 hash 的几个位置都算出
来,看看位数组中这几个位置是否都位 1,只要有一个位为 0,那么说明布隆过滤器中这个key 不存在。如果都是 1,这并不能说明这个 key 就一定存在,只是极有可能存在,因为这些位被置为 1 可能是因为其它的 key 存在所致。如果这个位数组比较小,这个概率就会很大,如果这个位数组比较大,这个概率就会降低。

使用时不要让实际元素远大于初始化大小,当实际元素开始超出初始化大小时,应该对布隆过滤器进行重建,重新分配一个 size 更大的过滤器,再将所有的历史元素批量 add 进去 (这就要求我们在其它的存储器中记录所有的历史元素)。因为 error_rate 不会因为数量超出就急剧增加,这就给我们重建过滤器提供了较为宽松的时间。

空间占用估计

有很多现成的网站已经支持计算空间占用的功能了,我们只要把参数输进去,就可以直接看到结果。

相关文章:

redis高级数据结构布隆过滤器

文章目录 背景什么是布隆过滤器Redis 中的布隆过滤器布隆过滤器使用注意事项实现原理空间占用估计 背景 我们在使用新闻客户端看新闻时,它会给我们不停地推荐新的内容,它每次推荐时要去重,去掉那些已经看过的内容。问题来了,新闻…...

mysql 5.7安装

基础环境:centos7.9 创建日志存放目录 mkdir -p /opt/supervisor/log安装相关工具 yum install -y perl net-tools numactl gcc python-devel配置yum源 sudo vim /etc/yum.repos.d/mysql-community.repo [mysql-connectors-community] nameMySQL Connectors Com…...

Golang:精通sync/atomic 包的Atomic 操作

在本指南中,我们将探索sync/atomic包的细节,展示如何编写更安全、更高效的并发代码。无论你是经验丰富的Gopher还是刚刚起步,你都会发现有价值的见解来提升Go编程技能。让我们一起开启原子运算的力量吧! 理解Go中的原子操作 在快…...

微信小程序如何使用decimal计算金额

第三方库地址:GitHub - MikeMcl/decimal.js: An arbitrary-precision Decimal type for JavaScript 之前都是api接口走后端计算,偶尔发现这个库也不错,计算简单,目前发现比较准确 上代码 导入js import Decimal from ../../uti…...

最新Modular公司之MAX和Mojo作者 克里斯·拉特纳简介

Chris Lattner(克里斯拉特纳) 是一位著名的计算机科学家和软件工程师,以其在编程语言、编译器技术和软件开发工具领域的贡献而闻名。以下是关于他的详细介绍: 1. 主要成就 (1)LLVM 项目的创始人 Chris La…...

Redis数据库篇 -- Pipeline

一. 什么是Pipeline 在传统的请求-响应模式中,客户端与服务器之间的通信流程如下: 客户端发送一个命令到服务器。服务器接收命令并执行。服务器将执行结果返回给客户端。客户端接收结果后,发送下一个命令 在这种传统的模式下,…...

爬虫自动化(DrissionPage)

目录 ?一.介绍: 下载DrissionPage,还是我们熟悉的pip: 环境准备: ?二.基本代码: 它对于的导包和类使用: 窗口的设置: 和获取的页面的滑动: 3.进一步认识DrissionPage: 浏览器可以多开…...

常见string库中的函数(C语言超详细)

文章目录 strcspnstrcpystrncpystrcatstrncatstrcmpstrncmpstrchrstrrchrstrstrstrtokstrlenstrnlen strcspn 原型: size_t strcspn(const char *str1, const char *str2);功能: strcspn 会扫描 str1,并返回一个整数,表示 str1 中第一个匹配…...

单例模式几种实现

静态内部类holder实现(推荐) public class UniqueIdGenerator {public static final UniqueIdGenerator INSTANCE Holder.INSTANCE;// Private holder class for lazy initializationprivate static class Holder {static final UniqueIdGenerator INS…...

android中关于CheckBox自定义选中图片选中无效问题

在android xml 布局中&#xff0c;使用CheckBox控件设置选中背景图代码如下 <CheckBoxandroid:layout_width"wrap_content"android:layout_height"wrap_content"android:button"drawable/dfrd_common_selecotr_check"android:paddingStart&q…...

虚拟局域网之详解(Detailed Explanation of Virtual Local Area Network)

虚拟局域网之详解 VLAN (virtual localArea network)是一种虚拟局域网技术&#xff0c;它可以将一个物理局域网划分为多个逻辑上的虚拟局域网。 基于交换式以太网的虚拟局域网在交换式以太网中&#xff0c;利用VLAN技术&#xff0c;可以将由交换机连接成的物理网络划分成多个…...

双亲委派(JVM)

1.双亲委派 在 Java 中&#xff0c;双薪委派通常是指双亲委派模型&#xff0c;它是 Java 类加载器的一种工作模式&#xff0c;用于确保类加载的安全性和一致性。以下是其相关介绍&#xff1a; 定义与作用 定义&#xff1a;双亲委派模型要求除了顶层的启动类加载器外&#xf…...

第二十一章:考研的艰难抉择与放弃入学的转折

深秋时节&#xff0c;校园宛如被大自然精心雕琢的艺术殿堂。金黄的银杏叶在阳光的轻抚下&#xff0c;闪烁着细碎的光芒&#xff0c;微风拂过&#xff0c;叶片相互摩挲&#xff0c;发出沙沙的轻响&#xff0c;仿佛在低声诉说着岁月的故事。一片片银杏叶悠悠然飘落&#xff0c;宛…...

webpack配置之---output.chunkLoading

output.chunkLoading webpack.output.chunkLoading 配置项用于指定 Webpack 如何加载异步 chunk&#xff08;即按需加载的代码块&#xff09;。在现代 Webpack 版本中&#xff0c;异步代码分割成为了非常常见的功能&#xff0c;chunkLoading 配置项就用于控制 Webpack 加载这些…...

升级RAG应用程序与Redis向量库

Redis Vector Library (RedisVL) 简化AI应用开发 几个月前&#xff0c;Redis推出了Redis向量库&#xff08;RedisVL&#xff09;&#xff0c;以简化人工智能&#xff08;AI&#xff09;应用的开发。自那时起&#xff0c;我们引入了强大的新功能&#xff0c;支持大规模的语言模…...

【starrocks学习】之将starrocks表同步到hive

目录 方法 1&#xff1a;通过HDFS导出数据 1. 将StarRocks表数据导出到HDFS 2. 在Hive中创建外部表 3. 验证数据 方法 2&#xff1a;使用Apache Spark同步 1. 添加StarRocks和Hive的依赖 2. 使用Spark读取StarRocks数据并写入Hive 3. 验证数据 方法 3&#xff1a;通过…...

HTML应用指南:利用GET请求获取全国盒马门店位置信息

随着新零售业态的发展,门店位置信息的获取变得至关重要。作为新零售领域的先锋,盒马鲜生不仅在商业模式创新上持续领先,还积极构建广泛的门店网络,以支持其不断增长的用户群体。本篇文章,我们将继续探究GET请求的实际应用,我们使用Python的requests库通过GET请求,从盒马…...

openEuler部署 sysstat工具

查看环境 [rootlocalhost lxm]# cat /etc/os-release NAME"openEuler" VERSION"23.09" ID"openEuler" VERSION_ID"23.09" PRETTY_NAME"openEuler 23.09" ANSI_COLOR"0;31"查看 yum 源 [rootlocalhost lxm]# he…...

使用 Three.js 实现炫酷的除夕烟花特效

1&#xff0c;前言 在除夕夜&#xff0c;璀璨的烟花点亮夜空&#xff0c;为节日增添了浓厚的喜庆氛围。在 Web 端&#xff0c;我们可以使用 Three.js 来模拟这种美轮美奂的烟花特效&#xff0c;让网页也能展现绚丽的节日气息。本文将介绍如何利用 Three.js 及其着色器技术&…...

LMM-3DP:集成 LMM 规划器和 3D 技能策略实现可泛化操作

25年1月来自UCSD的论文“Integrating LMM Planners and 3D Skill Policies for Generalizable Manipulation”。 大型多模态模型 (LMM) 的视觉推理能力和 3D 特征场语义丰富性的最新进展&#xff0c;拓展了机器人能力的范围。这些发展对于弥合 LMM 高级推理与利用 3D 特征场低…...

别再只用M法了!手把手教你用Arduino和旋转编码器实现M/T法测速(附代码)

别再只用M法了&#xff01;手把手教你用Arduino和旋转编码器实现M/T法测速&#xff08;附代码&#xff09; 在电机控制项目中&#xff0c;精确的速度测量往往是实现闭环控制的第一步。许多初学者会直接采用简单的M法&#xff08;频率测量法&#xff09;&#xff0c;但在实际测试…...

工业相机LUCID TRI050S偏振模式实战:从开箱到计算AOP/DOP的保姆级避坑指南

工业相机LUCID TRI050S偏振模式实战&#xff1a;从开箱到计算AOP/DOP的保姆级避坑指南 当你第一次拿到LUCID TRI050S这款工业级偏振相机时&#xff0c;可能会被它小巧的金属机身和复杂的接口配置所震撼。与普通工业相机不同&#xff0c;这款设备在每个像素点前都集成了微型偏振…...

vLLM-v0.17.1应用场景:跨境电商多语言商品描述生成系统

vLLM-v0.17.1应用场景&#xff1a;跨境电商多语言商品描述生成系统 1. 跨境电商面临的商品描述挑战 跨境电商企业每天需要为成千上万的商品生成多语言描述&#xff0c;传统人工编写方式面临三大痛点&#xff1a; 人力成本高&#xff1a;每个语种都需要专业翻译人员&#xff…...

8086汇编实战:用ZF、PF、SF标志位调试你的第一个程序(附调试截图)

8086汇编实战&#xff1a;用ZF、PF、SF标志位调试你的第一个程序&#xff08;附调试截图&#xff09; 刚接触汇编语言时&#xff0c;很多人会被那些神秘的标志位搞得一头雾水。记得我第一次在调试器里看到ZF、PF、SF这些缩写时&#xff0c;完全不明白它们有什么用——直到我在实…...

OpenOCD配置文件进阶指南:手把手教你定制STM32F0x的swj-dp.tcl脚本

OpenOCD深度定制&#xff1a;STM32F0x调试接口脚本开发实战 嵌入式开发中&#xff0c;调试工具的灵活配置往往决定着开发效率。对于STM32F0x系列芯片而言&#xff0c;OpenOCD作为开源调试工具链的核心组件&#xff0c;其配置文件的可定制性为开发者提供了极大的灵活性。本文将深…...

ADRV9009+ZCU102实战:从HDL工程构建到no-OS移植的5个关键步骤

ADRV9009ZCU102全流程开发指南&#xff1a;从HDL工程构建到no-OS移植的深度实践 在射频系统开发领域&#xff0c;ADRV9009作为一款高性能射频收发器&#xff0c;与Xilinx ZCU102开发板的组合已成为许多硬件工程师的首选方案。本文将深入剖析五个关键环节的技术细节&#xff0c;…...

LM386集成功放电路实战:从零搭建到波形调试全记录(附实测数据)

LM386集成功放电路实战&#xff1a;从零搭建到波形调试全记录&#xff08;附实测数据&#xff09; 在电子设计领域&#xff0c;音频功率放大器一直是基础却充满挑战的课题。LM386作为经典的集成功放芯片&#xff0c;以其低功耗、高增益和易用性著称&#xff0c;成为入门者和资深…...

超好看的Win10音量控制工具Eartrumpet

链接&#xff1a;https://pan.quark.cn/s/48beeba09372Eartrumpe是一款非常好用的系统音量控制工具&#xff0c;可以针对不同的应用进行音量控制&#xff0c;让你同时播放多个音频&#xff0c;在打游戏的时候可以调小游戏声音播放音乐&#xff0c;有需要的朋友欢迎下载使用&…...

免费降AI率和付费降AI率差距有多大?降论文ai率效果实测对比

免费降AI率和付费降AI率差距有多大&#xff1f;降论文ai率效果实测对比 “有没有免费的降AI率工具&#xff1f;” 这是毕业季被问得最多的问题之一。毕竟论文查重已经花了一笔钱&#xff0c;再加上降AI率的费用&#xff0c;对学生来说确实是一笔不小的开支。 但免费降AI率方案真…...

SAM3问题解决:分割不准?试试调整检测阈值和提示词

SAM3问题解决&#xff1a;分割不准&#xff1f;试试调整检测阈值和提示词 1. 问题现象与原因分析 1.1 常见分割问题表现 在使用SAM3进行图像分割时&#xff0c;用户可能会遇到以下几种典型问题&#xff1a; 过度分割&#xff1a;一个物体被分割成多个不连续的部分欠分割&am…...