布隆过滤器详讲

本文旨在讲解布隆过滤器的原理以及实现方式,希望通过本文能使读者对布隆过滤器有一定的认识!

一、布隆过滤器的引入

在讲解布隆过滤器之前,我们还是先提及一下前面讲的位图行,位图可以处理大量的数据,广泛用于查找等操作!但是对于位图而言,起能处理的类型只能是整形,那么对于字符串等其他类型位图是无法处理的,那么这时就引进了我们下面要讲的布隆过滤器!

下面来介绍什么是布隆器,正如前面说的,位图不能处理字符串等类型,那么我们该怎么办呢,因为我们前面学习过哈希,所以我们可以使用哈希的思想将字符串类型先转化为整形,利用哈希将字符串转化为整形的方法有很多,下面来看一下常见的几种字符串哈希算法。

字符串哈希算法:

1.BKDRhash

该算法就是该字符串的每个字符的ascii码值乘上一个数,然后再进行相加! 

 2. SDBMhash


3.DJBhash


4.APhash

通过观察上述字符串哈希,我们可以发现,基本上都是字符串中的每一位乘上一个数然后进行获取最终结果的 。


布隆过滤器的介绍以及应用场景!

既然介绍了这些字符串哈希函数,那么我们就来讲一下布隆过滤器是如何诞生以及实现的,上面已经提到了,因为位图不能处理非整形的数据,那么面对一个非整形的数据,我们就需要进行一次哈希函数将其转化为整形,然后再进行映射到地址中去,但是对于字符串哈希函数,我们很难保证没有不同的字符串对应有相同的数字,此时再进行某一位的映射时,就会导致误差!例如:

对于上图,如果middle与end的对应的整形相同,那么就会映射在同一块区域,那么当end不存在的时候,但是middle存在的时候,就会导致误判,误判end也存在!这时有人就想出来将一个字符串对应多个哈希函数,这样误判会不会结束呢?答案是否定的!误判是肯定不会不存在的!但是会减少!字符串与对应值有着多对一的关系。我们也可以发现,这种误判只会出现在‘存在的情况!’对于“不存在”的情况,是一定准确的!所以就有人说了,那么发明这种东西有什么用呢?这时我们的大佬布隆在发明他的时候已经想到了应用场景,即其可以筛选一定的情况,从而加快查找的速率!

布隆过滤器的应用:

我们平时都玩过游戏,有很多游戏都需要用户自己定义自己的名字,但是还不能有重名的情况!对于游戏中所有的用户名,全部都存储在服务器中的数据库中,但是如果我们每次起一个名字,都要去访问服务器中的数据库,那岂不是太浪费时间了!

上图就是我们起一个名字的时候,当我们点击提交昵称的时候,会自动取服务器中的数据库中进行查询,如果查询到了有重复,就会给用户提示改昵称已经存在了,请在换个名字,这时,每当用户起一个名字那岂不是都得取服务器中的数据库进行查找一番么?

对与此问题,我们布隆大佬就想到,为何不在二者之间加上一个布隆过滤器呢,可以大大减少我们的查找时间呀!

 当添加过了布隆过滤器的时候,我们可以不用访问服务器中的数据库,直接通过布隆过滤器的返回结果进行判断,就像我们输入昵称的时候,还没有点击提交的时候,昵称旁边就是出现对号或错号的提示!这其实就是利用了布隆过滤器!但是布隆过滤器也存在问题,就是其结果只能准确的判断一个字符不存在,对与存在的情况,会出现误判,但是这时如果有的玩家好奇心强,我起了十个名字,8个不能用,我非得查一查这些名字都是谁在用,不查不知道,一查吓一跳,有的昵称竟然不存在也不让我起!必须反手一波举报,于是针对布隆过滤器的特性,我们增加一下条件即可!对于布隆过滤器中返回存在的昵称,因为其不一定准确,所以我们将这些昵称读取到服务器中即可!再次进行一次准确的检查再反馈给用户即可!

这样布隆过滤器的作用就起了很大的作用!大大增加了我们工作的效率!其实生活中也有很多存在使用布隆过滤器的场景,例如大量的数据中查询某一个人的信息,如果我们暴力查找,挨个去服务器中的数据库一一进行查找,那么效率会非常低下,此时我们就会先将标记某一个人的唯一信息,例如身份证号,手机号 转化为整形,再对相同的整形中进行服务器内部查询,即可快速完成查询信息!


二、布隆过滤器的实现!

既然布隆过滤器的作用以及讲解完毕,接下来我们看一下布隆过滤器是如何实现的吧!

对于布隆过滤器而言,其本质上还是一个位图,只不过该位图对应的哈希值有多个而已!所以我们只需要实现set函数,将其对应的多个位都set为1即可!!进行test的时候我们只需要将其对应的位都进行检测一波,如果有false就返回false即可,全为true再返回true,此时我们的true也不一定是准确的!因为会存在不同字符串的映射值可能相同的情况!但是我们的fasle是一定准确的!

下面就来看一下我们实现的布隆过滤器吧!

#pragma once
//布隆过滤器的实现!
//其本质上还是一个位图!
#include<string>
#include<bitset>struct BKDRHash
{size_t operator()(const string& key){// BKDRsize_t hash = 0;for (auto e : key){hash *= 31;hash += e;}return hash;}
};struct APHash
{size_t operator()(const string& key){size_t hash = 0;for (size_t i = 0; i < key.size(); i++){char ch = key[i];if ((i & 1) == 0){hash ^= ((hash << 7) ^ ch ^ (hash >> 3));}else{hash ^= (~((hash << 11) ^ ch ^ (hash >> 5)));}}return hash;}
};struct DJBHash
{size_t operator()(const string& key){size_t hash = 5381;for (auto ch : key){hash += (hash << 5) + ch;}return hash;}
};template<size_t N,class K = string,class HashFunc1 = BKDRHash,class HashFunc2 = APHash,class HashFunc3 = DJBHash>
class BloomFilter
{
public://set功能!  因为布隆过滤器其对应有多个映射值,所以我们使用多个哈希进行位映射!将对应的位置为1即可!!void set(const K& x){size_t hash1 = HashFunc1()(x)%N;   //对N进行取余,保证其在这些空间上,防止因转化为整形过大!size_t hash2 = HashFunc2()(x)%N;   //对N进行取余,保证其在这些空间上,防止因转化为整形过大!size_t hash3 = HashFunc3()(x)%N;   //对N进行取余,保证其在这些空间上,防止因转化为整形过大!//对三个映射的位统统进行置一处理!!bt.set(hash1);bt.set(hash2);bt.set(hash3);}//test功能!  检测该字符是否存在,只需要将其对应的位进行test即可,如果有一个不存在直接返回false,//当三个都存在返回true即可,但是此时的true也是一种不准确的值!bool test(const K& key){size_t hash1 = HashFunc1()(key) % N;   //对N进行取余,保证其在这些空间上,防止因转化为整形过大!size_t hash2 = HashFunc2()(key) % N;   //对N进行取余,保证其在这些空间上,防止因转化为整形过大!size_t hash3 = HashFunc3()(key) % N;   //对N进行取余,保证其在这些空间上,防止因转化为整形过大!if (bt.test(hash1) == false){return false;}else if (bt.test(hash2) == false){return false;}else if (bt.test(hash3) == false){return false;}//当三者都为true时,才true!但是此时的true也是一个不准确的值!else if (bt.test(hash1) == true && bt.test(hash2) == true && bt.test(hash3) == true){return true;}}private:std::bitset<N>bt;   //本质上还是一个位图!
};

我们首先做的就是实现三个字符串哈希函数,用于我们的字符串映射的多个值问题!

细心的小伙伴们可能发现了,我没有实现reset函数,我为什么没有实现呢?对与布隆过滤器,其大多是不支持删除的!因为一个字符可能对应多个哈希值,某一位可能与已经存在的一位相同,如果将该位删除,那么与其相同的位也会删除掉,这就会导致误删的现象,但是我们可以使用引用计数的方法来解决reset的问题!

既然我们的布隆过滤器已经实现了,那么我们就简单的进行测试一下其效果吧!

我们将“数据结构”set到过滤器中,然后找一个与其比较相似的字符串“数据结构  ”进行测试,显然其不存在于我们的过滤器中,看来我们的布隆过滤器效果还是蛮不错的嘛! 

1.相似字符串的误判率

下面我们来看一下大量的相似字符串的误判率!

 2.不相似字符串的误判率

我们把数据个数N调到1000来观察一下结果!

根据结果还是容易看出来:相似字符串的误判率还是比较大的,那么这个误判率与什么有关系呢?

我把文章链接贴在下面:感兴趣的小伙伴可以看一下布隆过滤器的误判率的影响!详解布隆过滤器的原理,使用场景和注意事项 - 知乎 (zhihu.com) 


至此布隆过滤器的知识讲述完毕,下面来看一下另一个知识,哈希切分!

三、哈希切分 

 我们看一道例题来引出我们哈希切分!

例1:给定两个100亿的query,我们只有1G内存,如何快速找到两者的交集!

那么我们传统的哈希/红黑树是肯定不行的。

这时我们就可以利用hash函数将两个大文件分割成500个小文件,这时平均每个小文件占1G内存,然后对相互对应的小文件,利用set进行求交集即可! 这时就会有小伙伴问为什么要找对应的小文件呢,因为我们使用的是哈希函数,字符串相同的肯定会映射在同一个位置,那么这时该问题,不就解决了么!

但是还会存在一个小问题,就是当小文件中的内存还是比较大的话,该怎么办呢?

小文件大分两种情况:

1.都是一样的字符串,这时直接利用set进行去重既可以解决问题!

2.不是相同的字符串,这时我们只需要进行换一种哈希函数重新进行分配即可!

例2:给定一个超过100G的log file,log中存储着ip地址,求log file中最多的ip地址!

本题也是相同的道理,因为是100G的文件,所以我们仍然可以采用哈希切分的思想进行切分为小文件,然后一一处理即可!这时我们大可不必再切500个小文件,我们可以切割成100个小文件,平均一个小文件占1G内存。

我们通过对ip地址的哈希进行哈希切分,切分成100个小文件,我们的哈希函数可以是这样的!

hashi=Hash(ip)%100;

这样相同的ip地址肯定会分到相同的小文件中,这时我们对每一个小文件进行map统计次数即可!


至此,我们的布隆过滤器和哈希切分讲解完毕,希望读完本篇文章,读者能有一定的收获,也希望大大多多评论留言,互相讨论一波!

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

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

相关文章

LoadBalance 负载均衡服务调用

前身:Ribbon LB负载均衡(Load Balance)是什么 简单的说就是将用户的请求平摊的分配到多个服务上&#xff0c;从而达到系统的HA&#xff08;高可用&#xff09;&#xff0c;常见的负载均衡有软件Nginx&#xff0c;LVS&#xff0c;硬件 F5等 spring-cloud-starter-loadbalancer组…

【独立开发前线】Vol.23 这个卖Excel课程的网站,月访问量14.5万,年销售额超过200万美金

今天要给大家分享的案例网站是&#xff1a;Miss-Excel 网址是&#xff1a;Miss Excel 这是一个专门销售Excel课程的网站&#xff0c;网址一共有18个系列的视频课程&#xff0c;最便宜的44美金&#xff0c;最贵的1197美金。所有的课程都是网站的创始人Kat Norton录制的&#xf…

C语言文件操作详解

文件是什么 在我们日常使用的电脑上我们在电脑磁盘上会看到许许多多的文件夹&#xff0c;那里面的东西其实就是文件&#xff0c;为什么我们要使用文件&#xff1f;那是因为我们的电脑肯定会要用来存储东西的&#xff0c;如果没有文件&#xff0c;那么我们的东西都全部存放在内…

【沐风老师】3DMAX顶点投影插件VertexProjection使用方法详解

3DMAX顶点投影插件VertexProjection使用教程 3DMAX顶点投影插件VertexProjection&#xff0c;将可编辑多边形顶点向下投影到网格对象表面。可以对可编辑多边形对象上的所有顶点或部分顶点进行投影。主要用于地形建模、道路交通等领域。 【适用版本】 3dMax 2010 - 2024&#x…

vue3路由代码示例

路由简单分三步吧 第一定义路由&#xff1a; 包括访问地址&#xff0c;对应组件 第二使用&#xff1a;在index.html中使用它 下面是代码示例&#xff1a; components/Person.vue <template><router-link to"/test/hello">跳转</router-link>&…

一键换脸的facefusion

FaceFusion 一个开源换脸软件&#xff0c;提供UI界面&#xff0c;启动后可直接在浏览器上面上传图片进行换脸操作。 电脑环境win10&#xff0c;软件pycharm&#xff0c;需要提前安装好python环境&#xff0c;推荐使用Anaconda3。关注文章下方公共号发送 “ 软件安装包 ”可以获…

Leetcode239_滑动窗口最大值

1.leetcode原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 2.题目描述 给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口…

夜莺浏览日志、filebeat采集日志(四)

文章目录 一、elasticsearch二、filebeat三、日志分析 一、elasticsearch docker启动 docker run -d -p 9200:9200 -p 9300:9300 --restartalways -e ES_JAVA_OPTS"-Xms512m -Xmx512m" \ -e discovery.typesingle-node -e xpack.security.enabledtrue -e ELASTIC_P…

plantegg-10+倍性能提升全过程–优酷账号绑定淘宝账号的TPS从500到5400的优化历程

原文地址:https://plantegg.github.io/2018/01/23/10%E5%80%8D%E6%80%A7%E8%83%BD%E6%8F%90%E5%8D%87%E5%85%A8%E8%BF%87%E7%A8%8B/ 背景说明 2016年的双11在淘宝上买买买的时候&#xff0c;天猫和优酷土豆一起做了联合促销&#xff0c;在天猫双11当天购物满XXX元就赠送优酷会…

什么是生态智慧公厕@光明源

生态智慧公厕是一种结合生态环保理念和智能科技的公厕设施。这种公厕旨在提供更加环保、节能、可持续的卫生解决方案&#xff0c;同时通过智能化技术提升管理效率和用户体验。生态智慧公厕通常具有以下特点&#xff1a; 节能环保&#xff1a;生态智慧公厕采用了各种节能环保技…

npm淘宝镜像源更新

目录 前情提要&#xff1a; 背景&#xff1a; 镜像源更新&#xff1a; 清楚缓存&#xff1a; 直接切换镜像源&#xff1a; 补充&#xff1a; 错误解释&#xff1a; 解决方法&#xff1a; 前情提要&#xff1a; 2024 /1 /22 &#xff0c;registry.npm.taobao.org淘宝镜像源的SSL…

【面试】Elasticsearch 在部署时,对 Linux 的设置有哪些优化方法?

Elasticsearch 在部署时&#xff0c;对 Linux 的设置有哪些优化方法&#xff1f; Elasticsearch是一个分布式搜索和分析引擎&#xff0c;它在Linux环境下的性能和稳定性可以通过一些优化方法进行提升。以下是一些针对Linux环境下Elasticsearch部署的优化方法&#xff1a; 1. 内…

【2024系统架构设计】案例分析- 3 数据库

目录 一 基础知识 二 真题 一 基础知识 1 ORM ORM(Object—Relationl Mapping

Java学习笔记(22)

缓冲流 真正操作数据的还是基本流 字节缓冲流 缓冲区是长度为8192的字节缓冲区 byte[] 8K Bufferedininputstream 读取数据就是把数据放到缓冲区中&#xff0c;字节长度默认长度8192 关流只需要关缓冲流&#xff0c;因为在底层会关基本流 一次读多个字节 字节缓冲流提高效…

XR虚拟直播间,引领创新风潮,打破直播局限!

随着互联网技术日新月异的发展&#xff0c;直播行业也迎来了蓬勃发展的春天。然而&#xff0c;大多数直播间在吸引观众眼球和延长用户观看时长方面&#xff0c;仍然面临着巨大的挑战。正是在这样的背景下&#xff0c;XR虚拟直播系统应运而生&#xff0c;以其多维度的直播场景、…

自然语言处理3(NLP)—— 机器学习

1. 自然语言处理在机器学习领域的主要任务 自然语言处理&#xff08;NLP&#xff09;在机器学习领域中扮演着至关重要的角色&#xff0c;旨在使计算机能够理解、解释和生成人类语言。以下是NLP在机器学习领域中的主要任务及其分类方法&#xff1a; 1.1 按照功能类型分类 1.1.…

Nacos的搭建和使用——SpringCloud Alibaba

1. 概要说明 在使用Nacos之前&#xff0c;请在你的虚拟机中下载好Nacos,再进行连接本机使用 port&#xff1a;8848 本机访问地址&#xff1a;http://{虚拟机ip}:8848/nacos/ 访问账号密码&#xff1a;nacos/nacos 2. Nacos的作用 2.1 服务发现中心 微服务将自身注册至Nacos&am…

Netty服务端基本启动流程源码刨析

前言: 希望看这篇文章之前对Java Nio编程比较熟悉&#xff0c;并有用过Netty开发简单代码 服务端代码 先大致说一下NioEventLoopGroup组件的作用&#xff0c;可以把它看是作内部维护了一个NioEventLoop数组的对象&#xff0c;它的构造方法的参数用来指定维护数组的大小。NioEve…

【Flutter 面试题】 Dart 是不是单线程模型?是如何运行的?

【Flutter 面试题】 Dart 是不是单线程模型&#xff1f;是如何运行的&#xff1f; 文章目录 写在前面口述回答补充说明示例&#xff1a;异步编程示例&#xff1a;使用 Isolates 处理计算密集型任务总结 写在前面 &#x1f64b; 关于我 &#xff0c;小雨青年 &#x1f449; CSD…

Echarts之x轴,Y轴配置项大全

ECharts是一个强大的数据可视化库&#xff0c;提供了丰富的配置项来定制图表的x轴和y轴。下面是ECharts中x轴和y轴的配置项大全&#xff1a; xAxis配置项&#xff1a; type&#xff1a;轴类型&#xff0c;可选值有&#xff1a;“value”&#xff08;数值轴&#xff09;, “cat…