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

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 中的布隆过滤器布隆过滤器使用注意事项实现原理空间占用估计 背景 我们在使用新闻客户端看新闻时,它会给我们不停地推荐新的内容,它每次推荐时要去重,去掉那些已经看过的内容。问题来了,新闻…...

《Wiki.js知识库部署实践 + CNB Git数据同步方案解析》

一、wiki.js 知识库简介 基本概述 定义 :Wiki.js 是一个开源、现代、轻量且功能强大的 Wiki 应用程序,基于 Node.js 构建,旨在帮助个人和团队轻松创建、管理和共享知识。开源性质 :它遵循 AGPLv3 许可证,任何人都可以…...

CSS Overflow 属性详解:控制内容溢出的利器

在前端开发中,处理内容溢出是一个常见的需求。CSS 提供了 overflow 属性,帮助我们控制当内容超出元素框时的显示方式。本文将详细介绍 overflow 属性的各种取值及其应用场景。 1. 什么是 overflow 属性? overflow 属性用于控制当元素的内容…...

.yml文件_YAML格式文件

.yml 文件是 YAML(YAML Ain’t Markup Language)格式的一种文件扩展名。YAML 是一种用于数据序列化的语言,通常用于配置文件、数据交换、日志记录等场景。它以可读性高、简洁的格式为特点,非常适合用于人类阅读和编写。YAML 通常被…...

根文件系统 Debian10【1】移植

1.开发背景 一般根文件系统使用 Busybox 或者是 Buildroot 构建,这样构建出来的文件系统比较小,但是不具备上网功能,扩展性比较差。随着 ARM 的日益强大,ARM 可以搭载更庞大复杂的系统,可以是 Ubuntu 或者 Debian 等发…...

【PyQt】实现格式刷功能

实现格式刷功能 在Qt Designer中直接实现格式刷功能并不支持,但可以通过以下方法在应用程序中实现类似功能: 一、Qt Designer中的替代方案 1.手动设置样式表 在属性编辑器中复制样式表(QSS)内容,粘贴到其他控件。 …...

Could not create task ‘:mainActivity:minifyReleaseWithR8‘.

最近接收了一个老项目,把项目clone下来后,总是报错,无法运行 Build-tool 33.0.1 is missing DX at D:\Android\Sdk\build-tools\33.0.1\dx.batFAILURE: Build failed with an exception.* What went wrong: Could not determine the depende…...

2025年日祭

本文将同步发表于洛谷(暂无法访问)、CSDN 与 Github 个人博客(暂未发布) 本蒟自2025.2.8开始半停课。 任务计划(站外题与专题) 数了一下,通过人数比较高的题,也就是我准备补的题&a…...

二维dp-地图

问题描述 传说,在蓝桥王国中一个极其神秘的森林。这个森林的起点在(1,1) ,终点在 (n,m)。在你进入这个森岭后,每次你只可以向下或者向右走,由于森岭的神秘力量,至多只可以改变 k 次方向。 小蓝现在想知道&#xff0c…...

Windows下AMD显卡在本地运行大语言模型(deepseek-r1)

Windows下AMD显卡在本地运行大语言模型 本人电脑配置第一步先在官网确认自己的 AMD 显卡是否支持 ROCm下载Ollama安装程序模型下载位置更改下载 ROCmLibs先确认自己显卡的gfx型号下载解压 替换替换rocblas.dll替换library文件夹下的所有 重启Ollama下载模型运行效果 本人电脑配…...

el-table表格点击单元格实现编辑

使用 el-table 和 el-table-column 创建表格。在单元格的默认插槽中,使用 div 显示文本内容,单击时触发编辑功能。使用 el-input 组件在单元格中显示编辑框。data() 方法中定义了 tableData,tabClickIndex: null,tabClickLabel: ,用于判断是否…...

数据库操作与数据管理——Rust 与 SQLite 的集成

第六章:数据库操作与数据管理 第一节:Rust 与 SQLite 的集成 在本节中,我们将深入探讨如何在 Rust 中使用 SQLite 数据库,涵盖从基本的 CRUD 操作到事务处理、数据模型的构建、性能优化以及安全性考虑等方面。SQLite 是一个轻量…...

Ubuntu 24.10 安装Deepseek(Ollama+openwebui)

一、Ollama安装 1.在线安装 curl -fsSL https://ollama.com/install.sh | sh 如果curl工具没有安装先执行如下命令 sudo apt install curl 验证curl是否安装成功 curl --version 安装的过程中会提示输入当前系统登录用户的密码。 安装提示success后,验证安装 ollama -…...

【漫话机器学习系列】084.偏差和方差的权衡(Bias-Variance Tradeoff)

偏差和方差的权衡(Bias-Variance Tradeoff) 1. 引言 在机器学习模型的训练过程中,我们常常面临一个重要的挑战:如何平衡 偏差(Bias) 和 方差(Variance),以提升模型的泛…...

STM32的HAL库开发---高级定时器---输出比较模式实验

一、高级定时器输出比较模式实验原理 定时器的输出比较模式总共有8种,本文使用其中的翻转模式,当TIMXCCR1TIMXCNT时,翻转OC1REF的电平,OC1REF为输出参考信号,高电平有效,OC1REF信号连接到0C1上面&#xff…...

[论文阅读] Knowledge Fusion of Large Language Models

Knowledge Fusion of Large Language Models (FuseLLM) Methodology 整体Pipeline如下图所示 不同的动物代表不同的LLM。左边第一,第二分别是Ensemble以及Weight Merging方法。最右侧为本文提出的FuseLLM。 Ensemble: 融合多个models的预测结果,比如…...

elementui:el-table支持搜索、切换分页多选功能,以及数据回显

1、el-table相关代码&#xff0c;需注意:row-key"(row) > { return row.id }" 以及 :reserve-selection"true" <div class"boxList"><div class"search-form"><!-- 搜索表单 --><el-form :inline"true&q…...

(ICLR=2025)生成的表征对齐:训练扩散Transformer比你想象的更简单

生成的表征对齐&#xff1a;训练扩散Transformer比你想象的更简单 paper是KAIST发表在ICLR 2025的工作 paper title:REPRESENTATION ALIGNMENT FOR GENERATION: TRAINING DIFFUSION TRANSFORMERS IS EASIER THAN YOU THINK Code&#xff1a;链接 ABSTRACT 最近的研究表明&…...

白嫖RTX 4090?Stable Diffusion:如何给线稿人物快速上色?

大家都知道&#xff0c;在设计的初期&#xff0c;我们通常会先绘制草图&#xff0c;然后再进行上色处理&#xff0c;最终才开始进行最终的设计工作。在这个上色的过程中&#xff0c;配色是至关重要的一环。这不仅方便了内部同事的评审&#xff0c;也让产品方和客户可以直观地了…...

Bash (Bourne-Again Shell)、Zsh (Z Shell)

文章目录 1. 历史背景2. 主要区别3. 功能对比自动补全插件和主题路径扩展提示符定制 4. 性能5. 使用场景6. 如何切换 Shell7. 总结 以下是 Bash 和 Zsh 之间的主要区别&#xff0c;列成表格方便对比&#xff1a; 特性BashZsh默认Shell大多数Linux发行版默认ShellmacOS默认She…...

pikachu[皮卡丘] 靶场全级别通关教程答案 以及 学习方法 如何通过渗透测试靶场挑战「pikachu」来精通Web渗透技巧? 一篇文章搞完这些问题

目录 Pikachu靶场 部署 暴力破解漏洞 学习地址: 靶场练习: 基于表单的暴力破解 验证码绕过(on server) 验证码绕过(on Client) token防爆破? XSS跨站脚本攻击 学习地址: 靶场练习&#xff1a; 反射型xss(get) 反射性xss(post) 存储型xss DOM型xss xss盲打 x…...

汽车零部件工厂如何借助安灯呼叫按钮盒提升生产响应速度

在现代汽车零部件工厂的生产环境中&#xff0c;高效的信息传递和快速的响应速度是确保生产顺畅运行的关键。然而&#xff0c;传统的口头呼喊或现场沟通方式往往存在信息传递慢、现场嘈杂、责任人难以及时找到等问题&#xff0c;尤其在设备故障或缺料时&#xff0c;这些问题会导…...

【0404】Postgres内核 实现分配一个新的 Object ID (OID)

文章目录 1. 分配一个新 Object ID (OID)1.1 ShmemVariableCache 中 nextOid1.2 写一个 NEXTOID log record1. 分配一个新 Object ID (OID) Postgres内核中分配一个新的 Oid 是由函数 GetNewObjectId() 实现。该函数声明于 transam.h,实现于 varsup.c 源文件。 对于 GetNewO…...

Idea 2024.3 使用CodeGPT插件整合Deepseek

哈喽&#xff0c;大家好&#xff0c;我是浮云&#xff0c;最近国产大模型Deepseek异常火爆&#xff0c;作为程序员我也试着玩了一下&#xff0c;首先作为简单的使用&#xff0c;大家进入官网&#xff0c;点击开始对话即可进行简单的聊天使用&#xff0c;点击获取手机app即可安装…...

「vue3-element-admin」告别 vite-plugin-svg-icons!用 @unocss/preset-icons 加载本地 SVG 图标

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template &#x1f33a; 仓库主页&#xff1a; GitCode︱ Gitee ︱ Github &#x1f496; 欢迎点赞 &#x1f44d; 收藏 ⭐评论 …...

C++自研3D教程OPENGL版本---动态批处理的基本实现

又开始找工作了&#xff0c;借机休息出去旅行两个月&#xff0c;顺便利用这段时间整理下以前写的东西。 以下是一个简单的动态批处理实现&#xff1a; #include <GL/glew.h> #include <GLFW/glfw3.h> #include <iostream> #include <vector>// 顶点结…...

docker /var/lib/docker/overlay2目录把磁盘空间占满问题

1、查看服务器磁盘空间 df -h果然100%了,docker系统文件把磁盘空间占满了。 2、进入overlay2目录&#xff0c;查找那个容器工作目录占用最高 cd /var/lib/docker/overlay2du -h --max-depth1详见下图 好家伙占用110G&#xff01;复制目录名称2c3c48ccac533c5d4a366d45a19bb9…...

SOA(面向服务架构)全面解析

1. 引言 什么是SOA&#xff08;面向服务架构&#xff09; SOA&#xff08;Service-Oriented Architecture&#xff0c;面向服务架构&#xff09;是一种将应用程序功能以“服务”的形式进行模块化设计的架构风格。这些服务是独立的功能模块&#xff0c;它们通过定义明确的接口…...

华为交换机堆叠配置

一、CSS堆叠集群配置&#xff08;框式交换机&#xff09; 1、通过集群卡连接方式组建集群 [SwitchA] set css mode css-card \\配置集群卡连接方式 [SwitchA] set css id 1 \\配置成员交换机的集群ID(缺省值为1) [SwitchA] set css priority 100 \\配…...

蓝桥杯备赛——进制转化相关问题

目录 一、基础概念 二、问题研究&#xff08;1&#xff09; 代码解读&#xff1a; 1. transfer 函数 代码功能概述 详细步骤 2. main 函数 代码功能概述 详细步骤 三、运用递归解决 &#xff08;一&#xff09; 代码如下&#xff1a; 代码解读&#xff1a; &#…...