十、Redis之布隆过滤器
文章目录布隆过滤器是什么布隆过滤器能干什么布隆过滤器原理hash冲突布隆过滤器使用添加坑位判断是否存在布隆过滤器使用场景解决缓存穿透的问题和redis结合bitmap使用黑名单校验识别垃圾邮件案例布隆过滤器优缺点布隆过滤器是什么布隆过滤器Bloom Filter由一个初值都为零的bit数组和多个哈希函数构成是一种用来快速判断“某个数据是否可能存在”的数据结构。它的特点是占用内存非常小 查询速度非常快 判断“肯定不存在”非常准确 判断“可能存在”时有一定概率出错一句话概括布隆过滤器说不存在就一定不存在说存在只是可能存在。布隆过滤器的组成布隆过滤器主要由两部分组成一个二进制数组 多个哈希函数例如有一个长度为 10 的二进制数组下标0 1 2 3 4 5 6 7 8 9 值 0 0 0 0 0 0 0 0 0 0 数组中的每个位置只能是 0没有被标记 1已经被标记布隆过滤器是一种类似set的数据结构只是统计结果在巨量数据下有点小瑕疵不够完美。布隆过滤器英语Bloom Filter是1970年由布隆提出的。它实际上是一个很长的二进制数组(00000000) 一系列随机hash算法映射函数主要用于判断一个元素是否在集合中。通常我们会遇到很多要判断一个元素是否在某个集合中的业务场景一般想到的是将集合中所有元素保存起来然后通过比较确定。链表、树、哈希表等等数据结构都是这种思路。但是随着集合中元素的增加我们需要的存储空间也会呈现线性增长最终达到瓶颈。同时检索速度也越来越慢上述三种结构的检索时间复杂度分别为O(n),O(logn),O(1)。这个时候布隆过滤器Bloom Filter就应运而生。布隆过滤器能干什么高效地插入和查询占用空间少但是返回的结果是不确定性不够完美布隆过滤器是一个二进制数组 一系列哈希函数组成。要知道在集合类只要用哈希函数基本上都会遇到哈希冲突这会导致某些key冲突占用同一个坑位比如三个key都占用上图5号坑位那么一个坑位的值表示三个key存在或不存在所以会有瑕疵。重点判断“可能存在”时有一定概率出错比如5号坑位现在值是1那么三个key中有几个存在存在的是哪一个或者是那几个没办法确定。判断“肯定不存在”非常准确判断不存在那么肯定就不存在布隆过滤器可以添加元素但是不能删除元素由于涉及hashcode判断依据删掉元素会导致误判率增加。布隆过滤器原理使用多个hash函数对key进行hash运算得到一个整数索引值对位数组长度进行取模运算得到一个位每个hash函数都会得到一个不同的位置将这几个位置都置1就完成了add操作。查询某个变量的时候我们只要看看这些点是不是都是1就可以大概率知道集合中有没有它了。如果这些点有任何一个为零则被查询变量一定不在。如果都是1则被查询变量很可能存在。为什么说是可能存在而不是一定存在呢那是因为映射函数本身就是散列函数散列函数是会有碰撞的。见上图3号坑两个对象都1这也是为什么不能删除的原因明明想要删除obj1但是顺带也会把obj2误删掉正是基于布隆过滤器的快速检测特性我们可以在把数据写入数据库时使用布隆过滤器做个标记。当缓存缺失后应用查询数据库时可以通过查询布隆过滤器快速判断数据是否存在。如果不存在就不用再去数据库中查询了。这样一来即使发生缓存穿透了大量请求只会查询Redis和布隆过滤器而不会积压到数据库也就不会影响数据库的正常运行。布隆过滤器可以使用Redis实现本身就能承担较大的并发访问压力。hash冲突哈希函数的概念是将任意大小的输入数据转换成特定大小的输出数据的函数转换后的数据称为哈希值或哈希编码也叫散列值如果两个散列值是不相同的根据同一函数那么这两个散列值的原始输入也是不相同的。这个特性是散列函数具有确定性的结果具有这种性质的散列函数称为单向散列函数。散列函数的输入和输出不是唯一对应关系的如果两个散列值相同两个输入值很可能是相同的但也可能不同这种情况称为“散列碰撞collision”。用hash表存储大数据量时空间效率还是很低当只有一个hash函数时还很容易发生哈希碰撞。布隆过滤器使用添加坑位当我们向布隆过滤器中添加数据时为了尽量地址不冲突会使用多个hash函数对key进行运算算得一个下标索引值然后对位数组长度进行取模运算得到一个位置每个hash函数都会算得一个不同的位置。再把位数组的这几个位置都置为1就完成了add操作。例如我们添加一个字符串wmyskxz对字符串进行多次hash(key)→ 取模运行 → 得到坑位1、3、5。判断是否存在向布隆过滤器查询某个 key 是否存在时先把这个 key 通过相同的多个 hash 函数进行运算查看对应的位置是否都为 1。只要有一个位为零那么说明布隆过滤器中这个 key 不存在如果这几个位置全都是 1那么说明极有可能存在因为这些位置的 1 可能是因为其他的 key 存在导致的也就是前面说过的 hash 冲突。。。。。就比如我们在 add 了字符串wmyskxz数据之后很明显下面 1/3/5 这几个位置的 1 是因为第一次添加的wmyskxz而导致的此时我们查询一个没添加过的不存在的字符串inexistent-key它有可能计算后坑位也是 1/3/5这就是误判了……笔记见最下面使用时最好不要让实际元素数量远大于初始化数量一次给够避免扩容当实际元素数量超过初始化数量时应该对布隆过滤器进行重建重新分配一个 size 更大的过滤器再将所有的历史元素批量 add进行。布隆过滤器使用场景解决缓存穿透的问题和redis结合bitmap使用缓存穿透是什么一般情况下先查询缓存 Redis 是否有该条数据缓存中没有时再查询数据库。当数据库也不存在该条数据时每次查询都要访问数据库这就是缓存穿透。缓存穿透带来的问题是当有大量请求查询数据库不存在的数据时就会给数据库带来压力甚至会拖垮数据库。可以使用布隆过滤器解决缓存穿透的问题把已存在数据的 key 存在布隆过滤器中相当于 Redis 前面挡着一个能量护照。当有新的请求时先到布隆过滤器中查询是否存在如果布隆过滤器中不存在该条数据则直接返回如果布隆过滤器中已存在才去查询缓存 Redis如果 Redis 里没查询到则再查询 MySQL 数据库。黑名单校验识别垃圾邮件发现存在黑名单中的就执行特定操作。比如识别垃圾邮件只要是邮箱在黑名单中的邮件就识别为垃圾邮件。假设黑名单的数量是数以亿计的存放起来就是非常耗费存储空间的布隆过滤器则是一个较好的解决方案。把所有黑名单都放在布隆过滤器中在收到邮件时判断邮件地址是否在布隆过滤器中即可。案例布隆过滤器根据代码逻辑redis缓存实现简单实现核心代码如下importch.qos.logback.classic.util.StatusViaSLF4JLoggerFactory;importlombok.extern.slf4j.Slf4j;importorg.apache.ibatis.transaction.managed.ManagedTransaction;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.stereotype.Component;importjavax.annotation.PostConstruct;importjavax.annotation.Resource;/** * 布隆过滤器白名单初始化工具类一开始就设置一部分数据为白名单所有 * 白名单业务默认规定布隆过滤器有redis是极大可能有。 * 白名单whitelistCustomer */ComponentSlf4jpublicclassBloomFilterInit{ResourceprivateRedisTemplateredisTemplate;PostConstruct//初始化白名单数据,暂时注释省的后台打印publicvoidinit(){//1 白名单客户加载到布隆过滤器Stringkeycustomer:12;//2 计算hashValue,由于存在计算出来负数的可能我们取绝对值inthashValueMath.abs(key.hashCode());//3 通过hashValue和2的32次方后取余获得对应的下标坑位longindex(long)(hashValue%Math.pow(2,32));log.info(key 二进制bit数组的位置index:{},index);//4 设置redis里面的bitmap对应类型白名单whitelistCustomer的坑位将该值设置为1redisTemplate.opsForValue().setBit(whitelistCustomer,index,true);}}上面的和的核心思想是先将初始化数据的key通过hashcode方法得到散列值然后取散列值的绝对值得到布隆过滤器的bit数组的位置然后存到的key为whitelistCustomer的的缓存中比如此时bit位是666那么此时比特位666的值是1。importlombok.extern.slf4j.Slf4j;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.stereotype.Component;importjavax.annotation.Resource;ComponentSlf4jpublicclassCheckUtils{ResourceprivateRedisTemplateredisTemplate;publicbooleancheckWithBloomFilter(StringcheckItem,Stringkey){inthashValueMath.abs(key.hashCode());longindex(long)(hashValue%Math.pow(2,32));booleanexistOKredisTemplate.opsForValue().getBit(checkItem,index);log.info(---key:key 对应坑位下标index: index 是否存在existOK);returnexistOK;}}分割线publicCustomerfindById(IntegercustomerId){Customercustomernull;//缓存key的名称StringkeyCACHA_KEY_CUSTOMERcustomerId;//布隆过滤器check无是绝对无有是可能有//if(!checkUtils.checkWithBloomFilter(whitelistCustomer,key)){log.info(白名单无此顾客不可以访问: key);returnnull;}////1 查询rediscustomer(Customer)redisTemplate.opsForValue().get(key);//redis无进一步查询mysqlif(customernull){//2 从mysql查出来customercustomercustomerMapper.selectByPrimaryKey(customerId);// mysql有redis无if(customer!null){//3 把mysql捞到的数据写入redis方便下次查询能redis命中。redisTemplate.opsForValue().set(key,customer);}}returncustomer;}findById是一个普通的service层的普通查询方法当获得查询参数id后直接拼接redis的key然后传递给checkWithBloomFilter。checkWithBloomFilter获取到key后调用hashcod方法获取散列值去redis的中查询如果查询到了返回ture否则返回false。然后findById根据true或false在决定直接响应结束还是查缓存或者是数据库。比如此刻传递过来的key经过hashCode算出来散列值是666checkWithBloomFilter会获取whitelistCustomer这个key的地666比特位的值饭后返回true或false。如果是黑名单用户我们已经添加布隆过滤器的缓存中了肯定能在缓存中查到所以就直接拒绝后续流程这样就可以有效过滤到一些我们不愿意的访问。以上就是一个简单的布隆过滤器的实现。布隆过滤器优缺点优点缺点不能删除元素。因为删掉元素会导致误判率增加因为hash冲突同一个位置可能存的东西是多个共有的你删除一个元素的同时可能也把其它的删除了。存在误判不能精准过滤。有是可能有无是肯定无。

相关新闻

Duix-Avatar 深度测评:13.6K Star 开源数字人,表现到底如何?

Duix-Avatar 深度测评:13.6K Star 开源数字人,表现到底如何?

T2 深度测评 工具类 2025 GitHub: https://github.com/GuijiAI/duix.ai ⭐ 13.6k 许可证:Apache-2.0 语言:Python / JavaScript 👤 测评人背景 做了十几年市场营销,这两年短视频和直播的浪潮逼得我必须学会「面对镜头」。但说…

2026/7/23 9:19:32 阅读更多 →
病理诊断行业报告里,国产设备为何总是“隐形“?

病理诊断行业报告里,国产设备为何总是“隐形“?

对于从事病理行业的人员来说,了解行业最新动态以及同行发展是一件非常重要的事情。判断正确了,可以让自己的企业在行业内更好的发展,判断错误,则会诱发失误决策,可能会给公司带来重大损失。 笔者也是一位在医疗行业从…

2026/7/23 9:19:32 阅读更多 →
无人机通信网络中的多智能体深度Q学习实践

无人机通信网络中的多智能体深度Q学习实践

1. 项目概述:无人机通信网络中的多智能体深度Q学习 去年夏天我在山区参与救灾时,亲眼目睹了传统通信基站损毁后,无人机临时组网如何成为生命线。这段经历让我深刻意识到,无人机网络的连接稳定性直接关系到应急通信的成败。本文将分…

2026/7/23 9:18:32 阅读更多 →

最新新闻

LTP与虚拟化技术:系统稳定性测试的黄金标准

LTP与虚拟化技术:系统稳定性测试的黄金标准

1. LTP与虚拟化技术概述 Linux Test Project(LTP)作为Linux系统最全面的自动化测试套件,其与虚拟化技术的结合正在重塑现代计算基础设施的验证方式。在嵌入式系统和云计算领域,这种组合已成为保障系统稳定性的黄金标准。我曾在多个…

2026/7/23 9:55:44 阅读更多 →
PCB 与 PCBA 到底有什么区别?一文理清电路板裸板与成品组件

PCB 与 PCBA 到底有什么区别?一文理清电路板裸板与成品组件

PCB 与 PCBA 到底有什么区别?一文理清电路板裸板与成品组件很多采购、设备工程师经常混淆 PCB 与 PCBA。简单概括:PCB 是空白线路基板,PCBA 是焊接元器件、具备完整电气功能的电路板总成。 PCB(Printed Circuit Board,…

2026/7/23 9:55:44 阅读更多 →
AI辅助测试生成实战:从单元测试到E2E测试的智能化落地

AI辅助测试生成实战:从单元测试到E2E测试的智能化落地

AI辅助测试生成实战:从单元测试到E2E测试的智能化落地 测试生成的三个核心层次 独立开发者的产品,测试覆盖率通常不足。不是"不知道测试重要",而是"写测试太耗时了"——一个功能写1小时,写测试可能要30分钟。…

2026/7/23 9:55:44 阅读更多 →
划分巧克力

划分巧克力

分巧克力 问题描述 儿童节那天有 KK 位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。 小明一共有 NN 块巧克力,其中第 ii 块是 HiWiH**iW**i 的方格组成的长方形。为了公平起见, 小明需要从这 NN 块巧克力中切出 K 块巧克力分给小朋友们。切…

2026/7/23 9:55:44 阅读更多 →
高效制作每日新闻播报的流程与技巧

高效制作每日新闻播报的流程与技巧

1. 每日新闻播报的价值与定位 每天早上醒来第一件事就是刷新闻,这已经成为现代人的生活习惯。但面对海量信息,如何高效获取真正有价值的资讯?这就是每日新闻播报存在的意义。不同于传统新闻媒体的长篇大论,每日新闻播报以精炼的形…

2026/7/23 9:55:44 阅读更多 →
Apollo配置中心实战:从原理到企业级部署应用指南

Apollo配置中心实战:从原理到企业级部署应用指南

最近在开发过程中,很多同学都遇到过配置信息需要频繁修改但又不想重启应用的情况。传统的配置文件方式每次更新都需要重新部署,严重影响开发效率和系统稳定性。本文将详细介绍如何使用携程开源的配置中心Apollo来解决这一痛点,从环境搭建到生…

2026/7/23 9:54:44 阅读更多 →

日新闻

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:25 阅读更多 →
AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

更多请点击: https://codechina.net 第一章:AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析 在对2,346篇跨行业AI生成文案的A/B测试数据进行聚类分析后,我们发现&#xff1…

2026/7/23 0:01:26 阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:01:26 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 8:58:19 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 19:43:43 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 12:54:44 阅读更多 →

月新闻