【数据结构】布隆过滤器

SueWakeup

                                                     个人主页:SueWakeup

                                                     系列专栏:学习技术栈

                                                     个性签名:保留赤子之心也许是种幸运吧

本文封面由 凯楠📸 友情提供

目录

本栏传送门 

前言

1. 什么是布隆过滤器? 

2. 布隆过滤器的原理 

2.2 判断元素存在原理

3. 布隆过滤器使用场景 

4. 使用 Java 语言实现布隆过滤器 

测试用例

测试结果

注:手机端浏览本文章可能会出现 “目录”无法有效展示的情况,请谅解,点击侧栏目录进行跳转 


本栏传送门 

1.【技术栈】Redis 的理解与数据存储格式

2.【技术栈】Redis 中的事务及持久化方式

3.【技术栈】Redis 删除策略

4.【技术栈】Redis 企业级解决方案

5.【数据结构】布隆过滤器

6.【开发】SpringBoot 整合 Redis

7.【技术栈】Spring Cache 简化 Redis 缓存使用


前言

        在使用 Redis 作缓存时,可能出现 “缓存穿透对不存在于Redis的数据发起请求,恶意或者误操作地使得大量的请求穿透缓存直接访问数据库,导致数据库压力过大)” 问题。为了防止 Redis 缓存穿透,可以使用 “布隆过滤器” 避免大量不存在的 key 直接访问数据库。


1. 什么是布隆过滤器? 

布隆过滤器(Bloom Filter)是由 Burton Howard Bloom 于 1970 年提出的 “位数组” 和 “一组哈希函数” 两部分组成,用于检查元素是否存在于指定集合中的数据结构。

  • 优点:高效且性能很好。

        位数组中的每个元素都只占用 1 bit,并且每个元素只能是 0 或者 1。申请 100w 个元素的位数组只占用 1000000 Bit / 8 = 125000 字节 = 125000字节 / 1024 ≈ 122 字节 的空间。

  • 缺点:具有一定的误判性(错误识别率)和删除难度。理论情况下,添加到集合中的元素越多,误判的可能性越大。

2. 布隆过滤器的原理 

2.1 添加元素原理

  1. 使用布隆过滤器中的哈希函数对元素值进行计算,得到哈希值(哈希值为多个)。
  2. 根据得到的哈希值,在位数组中把对应下标的值 “置为1”。

2.2 判断元素存在原理

  1. 对给定元素再次进行相同的哈希计算。
  2. 得到值之后判断位数组中的每个元素是否都为 1,如果都为 1,则说明这个元素可能存在于布隆过滤器中,如果存在一个值不为 1,说明该元素不在布隆过滤器中。

为什么说 “位数组” 中的每个元素都为1,这个元素可能存在于布隆过滤器中?

  • 一方面,判断元素存在需要对给定元素进行哈希计算,哈希计算的 “范围” 受 Integer 的MIN_VALUE(-2 ^ 31) 和 MAX_VALUE(2 ^ 31 - 1)影响,范围有限,不同的元素的哈希计算可能出现同一个哈希值。
  • 另一方面,在布隆过滤器 “添加元素” 时,我们会对给定元素进行多次哈希计算避免 “哈希冲突(哈希函数计算得到相同的哈希码)”,所以,两个不同的元素分别进行多次哈希计算,某次计算的哈希码在位数组的指向可能为同一个位置(如图所示)。

  • 故,位数组中的每个元素都为1,这个元素可能存在于布隆过滤器中。
  • 但是,都不为1,这个元素肯定不存在于布隆过滤器中。

这个说法,在后文中 “使用 Java 语言实现布隆过滤器” 有体现


3. 布隆过滤器使用场景 

  • 判断给定数据是否存在:  
    • 判断一个数字是否存在于 “包含大量数字” 的数字集合中(5 亿)。
    • 防止 “缓存穿透”(判断请求的数据是否有效避免直接绕过缓存请求数据库)。
    • 邮箱的垃圾邮件过滤、黑名单功能等。
  • 去重
    • 爬虫程序对已经爬取过的 URL 去重。

4. 使用 Java 语言实现布隆过滤器 

思路:

  1. 一个合适大小的位数组保存数据。
  2. 几个不同的哈希函数。
  3. 添加元素到位数组(布隆过滤器)的方法实现。
  4. 判断给定元素是否存在于位数组(布隆过滤器)的方法实现。
public class MyBloomFilter {// ①位数组的长度private static final int DEFAULT_SIZE = 2 << 24; //2^24// ③初始化位数组private BitSet bits =new BitSet(DEFAULT_SIZE);// ④一组哈希函数(哈希操作)private static final int[] SEEDS = new int[] {3,13,46,71,91,134}; // 散列的种子数组private SimpleHash[] hashOps = new SimpleHash[SEEDS.length];// ⑤过滤器构造方法public MyBloomFilter(){for(int i =0;i<hashOps.length;i++){hashOps[i] = new SimpleHash(DEFAULT_SIZE,SEEDS[i]);}}// ⑥添加元素public void add(Object value){for(SimpleHash sh :hashOps){bits.set(sh.hash(value),true);}System.out.println(bits);}// ⑦判断元素是否存在public boolean contains(Object value){boolean ret = true;for(SimpleHash sh : hashOps){ret = ret && bits.get(sh.hash(value));}return ret;}// ②哈希操作static class SimpleHash{private int cap; //容量private int seed; //种子public SimpleHash(int cap,int seed){this.cap = cap;this.seed = seed;}//哈希函数public int hash(Object value){int h;return value == null ? 0 : Math.abs(seed * (cap -1) & ((h =value.hashCode()) ^ (h >>>16)));}}
}

测试用例

public class BloomFilterTest {public static void main(String[] args) {MyBloomFilter myBloomFilter = new MyBloomFilter();myBloomFilter.add(131);myBloomFilter.add(110);myBloomFilter.add(120);myBloomFilter.add(119);myBloomFilter.add(114);System.out.println(myBloomFilter.contains(112));}
}

测试结果

{2, 129, 130, 131}
{2, 36, 40, 66, 98, 106, 108, 129, 130, 131}
{2, 32, 36, 40, 56, 66, 80, 98, 106, 108, 112, 120, 129, 130, 131}
{2, 32, 36, 37, 40, 49, 56, 66, 80, 82, 98, 106, 108, 112, 114, 115, 117, 120, 129, 130, 131}
{2, 32, 36, 37, 40, 48, 49, 56, 66, 80, 82, 98, 106, 108, 112, 114, 115, 117, 120, 129, 130, 131}
true

在此, “位数组” 中的每个元素都为1,这个元素可能存在于布隆过滤器中的说法 得到了验证。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/762945.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用虚拟机安装FydeOS,体验国内版ChromeOS首选!

前言 前段时间小白写了在实体机上安装FydeOS系统&#xff0c;发现有很多小伙伴在后台获取了FydeOS的镜像。 国内版ChromeOS&#xff1f;让旧机器焕发第二春的FydeOS安装教程 也有一些小伙伴看到是安装在实体机上的教程&#xff0c;所以就直接放弃了。其实FydeOS也可以用VM…

面试笔记——MySQL(事务:事务特性、并发事务、事务隔离、Redo Log与Undo Log、MVCC)

事务 概念与特性 事务&#xff08;Transaction&#xff09;指的是一组数据库操作&#xff0c;这些操作要么全部成功执行&#xff0c;要么全部不执行&#xff0c;保证了数据库的一致性和完整性&#xff0c;它使得数据库操作可以按照逻辑上的单元进行组织和执行&#xff0c;提高…

中等职业学校大数据课程建设方案

大数据产业是以数据及数据所蕴含的信息价值为核心生产要素&#xff0c;通过数据技术、数据产品、数据服务等形式&#xff0c;使数据与信息价值在各行业经济活动中得到充分释放的赋能型产业。 大数据产业定义一般分为核心业态、关联业态、衍生业态三大业态。 一、专…

Nginx实现原理全解析:构建高效Web服务器的关键

1、Nginx是什么 Nginx&#xff08;engine X&#xff09;是一个开源的轻量级的HTTP服务器&#xff0c;能够提供高性能的HTTP和反向代理服务。与传统的Apache服务器相比&#xff0c;在性能上Nginx占用系统资源更小、支持高并发&#xff0c;访问效率更高&#xff1b;在功能上&…

Doris实战——工商信息查询平台的湖仓一体建设

目录 前言 一、架构1.0&#xff1a;传统Lambda架构 二、OLAP引擎调研 三、架构2.0&#xff1a;数据服务层All in Apache Doris 四、架构 3.0&#xff1a;基于Doris Multi-Catalog的湖仓一体架构 五、实践经验 5.1 引入Merge-on-Write&#xff0c;百亿级单表查询提速近三…

谷歌DeepMind推出3D游戏AI代理SIMA,实现自然语言操控游戏新纪元

近日&#xff0c;谷歌DeepMind研究团队推出了一款名为SIMA的创新AI代理&#xff0c;专为3D游戏环境设计。这款代理独树一帜&#xff0c;无需访问游戏源代码或依赖定制API&#xff0c;仅通过输入图像和简单的自然语言文本指令&#xff0c;便能实现与人类玩家相当的游戏操作。 AI…

LangChain教程 | langchain 文件加载器使用教程 | Document Loaders全集

提示&#xff1a; 想要了解更多有关内置文档加载器与第三方工具集成的文档&#xff0c;甚至包括了&#xff1a;哔哩哔哩网站加载器、区块链加载器、汇编音频文本、Datadog日志加载器等。 本文主要收集与讲解日常使用的加载器&#xff0c;足够咱们平时开发人工智能的工作使用&am…

【前端性能】前端性能指标和测量方法总结

文章目录 前端性能指标和测量方法总结重要指标名词概念指标测量方法performance APIChrome PerformanceChrome Lighthouseweb-vitals 前端性能指标和测量方法总结 重要指标名词概念 图源 https://dev.to/xnimorz/hitchhiker-s-guide-to-frontend-performance-optimization-460…

计算机+任何行业都等于王炸!

最近笔者刷到一则消息&#xff0c;一位测试员在某乎上分享&#xff0c;从月薪5K到如今的20K&#xff0c;他总共跳了10次槽&#xff0c;其中还经历过两次劳动申诉&#xff0c;拿到了大几万的赔偿&#xff0c;被同事们称为“职场碰瓷人”。 虽说这种依靠跳槽式的挣钱法相当奇葩&a…

Java微服务分布式事务框架seata的TCC模式

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 往期热门专栏回顾 专栏…

鸿蒙ArkTS实战开发-Native XComponent组件的使用

介绍 本篇Codelab主要介绍如何使用XComponent组件调用NAPI来创建EGL/GLES环境&#xff0c;实现在主页面绘制一个正方形&#xff0c;并可以改变正方形的颜色。本篇CodeLab使用Native C模板创建。 如图所示&#xff0c;点击绘制矩形按钮&#xff0c;XComponent组件绘制区域中渲…

Sketch软件:重塑UI/UX设计流程的革命性工具

Sketch是一款在Mac操作系统上运行的矢量图形设计软件&#xff0c;其功能特色丰富多样&#xff0c;深受设计师们的喜爱。以下是Sketch软件的主要功能特色介绍&#xff1a; 专业矢量图形设计&#xff1a;Sketch为UI设计、移动应用设计和Web设计等领域提供了强大的支持。它支持线条…

探索ChatGPT时代下的下一代信息检索系统:机遇与挑战

1 Introduction 2022 年 11 月 30 日&#xff0c;OpenAI 推出了 ChatGPT&#xff0c;这是一款由先进的 GPT3.5 和更高版本的 GPT-4 生成语言模型提供支持的 AI 聊天机器人应用程序。该应用迅速吸引了全球超亿用户&#xff0c;创下了产品快速传播的新纪录。 它能够以对话的方式…

ElasticSearch 用法

首先讲下 ES的倒排序索引 创建倒排索引是对正向索引的一种特殊处理&#xff0c; 将每一个文档的数据利用算法分词&#xff0c;得到一个个词条 创建表&#xff0c;每行数据包括词条、词条所在文档id、位置等信息 因为词条唯一性&#xff0c;可以给词条创建索引&#xff0c;例如…

旅游小程序开发的费用及功能

随着科技的发展和智能手机的普及&#xff0c;越来越多的行业开始利用小程序来进行线上服务。旅游业作为一个重要的服务业&#xff0c;也纷纷推出了自己的旅游小程序&#xff0c;以方便游客在线预订、查询景点信息等。那么&#xff0c;旅游小程序开发的费用是多少&#xff1f;功…

Google研究者们提出了VLOGGER模型

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【探索Linux】—— 强大的命令行工具 P.29(网络编程套接字 —— 简单的TCP网络程序模拟实现)

阅读导航 引言一、TCP协议二、TCP网络程序模拟实现1. 预备代码⭕ThreadPool.hpp&#xff08;线程池&#xff09;⭕makefile文件⭕打印日志文件⭕将当前进程转变为守护进程 2. TCP 服务器端实现&#xff08;TcpServer.hpp&#xff09;3. TCP 客户端实现&#xff08;main函数&…

babyos 学习记录

宏定义头文件 将一个宏定义取不同的数据到不同的数组中&#xff1b; 侵入式链表 struct list_head { struct list_head *next, *prev; }; // 添加&#xff08;list_add_tail/list_add&#xff09;、删除、查找 xx.h // 定义一个用于链表管理的结构体 typedef sturct{ xxx …

matlab矩形薄板小挠度弯曲有限元编程 |【Matlab源码+理论文本】|板单元| Kirchoff薄板 | 板壳单元

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

分库分表场景下多维查询解决方案(用户+商户)

在采用分库分表设计时&#xff0c;通过一个PartitionKey根据散列策略将数据分散到不同的库表中&#xff0c;从而有效降低海量数据下C端访问数据库的压力。这种方式可以缓解单一数据库的压力&#xff0c;提升了吞吐量&#xff0c;但同时也带来了新的问题。对于B端商户而言&#…