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 布局中,使用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)是一种虚拟局域网技术,它可以将一个物理局域网划分为多个逻辑上的虚拟局域网。 基于交换式以太网的虚拟局域网在交换式以太网中,利用VLAN技术,可以将由交换机连接成的物理网络划分成多个…...
双亲委派(JVM)
1.双亲委派 在 Java 中,双薪委派通常是指双亲委派模型,它是 Java 类加载器的一种工作模式,用于确保类加载的安全性和一致性。以下是其相关介绍: 定义与作用 定义:双亲委派模型要求除了顶层的启动类加载器外…...
第二十一章:考研的艰难抉择与放弃入学的转折
深秋时节,校园宛如被大自然精心雕琢的艺术殿堂。金黄的银杏叶在阳光的轻抚下,闪烁着细碎的光芒,微风拂过,叶片相互摩挲,发出沙沙的轻响,仿佛在低声诉说着岁月的故事。一片片银杏叶悠悠然飘落,宛…...
webpack配置之---output.chunkLoading
output.chunkLoading webpack.output.chunkLoading 配置项用于指定 Webpack 如何加载异步 chunk(即按需加载的代码块)。在现代 Webpack 版本中,异步代码分割成为了非常常见的功能,chunkLoading 配置项就用于控制 Webpack 加载这些…...
升级RAG应用程序与Redis向量库
Redis Vector Library (RedisVL) 简化AI应用开发 几个月前,Redis推出了Redis向量库(RedisVL),以简化人工智能(AI)应用的开发。自那时起,我们引入了强大的新功能,支持大规模的语言模…...
【starrocks学习】之将starrocks表同步到hive
目录 方法 1:通过HDFS导出数据 1. 将StarRocks表数据导出到HDFS 2. 在Hive中创建外部表 3. 验证数据 方法 2:使用Apache Spark同步 1. 添加StarRocks和Hive的依赖 2. 使用Spark读取StarRocks数据并写入Hive 3. 验证数据 方法 3:通过…...
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,前言 在除夕夜,璀璨的烟花点亮夜空,为节日增添了浓厚的喜庆氛围。在 Web 端,我们可以使用 Three.js 来模拟这种美轮美奂的烟花特效,让网页也能展现绚丽的节日气息。本文将介绍如何利用 Three.js 及其着色器技术&…...
LMM-3DP:集成 LMM 规划器和 3D 技能策略实现可泛化操作
25年1月来自UCSD的论文“Integrating LMM Planners and 3D Skill Policies for Generalizable Manipulation”。 大型多模态模型 (LMM) 的视觉推理能力和 3D 特征场语义丰富性的最新进展,拓展了机器人能力的范围。这些发展对于弥合 LMM 高级推理与利用 3D 特征场低…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案
在大数据时代,海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构,在处理大规模数据抓取任务时展现出强大的能力。然而,随着业务规模的不断扩大和数据抓取需求的日益复杂,传统…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...
AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
GAN模式奔溃的探讨论文综述(一)
简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...
