【Redis | 第五篇】一篇文章看懂布谷鸟过滤器

文章目录

  • 5.布谷鸟过滤器
    • 5.1起源介绍
    • 5.2原理
      • 5.2.1演示步骤
        • (1)保存元素(两个位置均为空)
        • (2)保存元素(其中一个位置被占)
        • (3)保存元素(两个位置都被占)
        • (4)被挤掉的元素重新找位置
      • 5.2.2问题
      • 5.2.4布谷鸟过滤器
        • (1)原理简述
        • (2)组成
        • (3)插入
        • (4)扩容
        • (5)查找
        • (6)删除
        • (7)删除全部
        • (8)更新
    • 5.3优缺点
      • 5.3.1优点
      • 5.3.2缺点
    • 5.4代码实现
    • 5.5总结

5.布谷鸟过滤器

参考文章链接:https://knife.blog.csdn.net/article/details/121279365

5.1起源介绍

布谷鸟算法的启发来自于布谷鸟,因为布谷鸟这种鸟很有意思,生出来的孩子自己不养,直接把孩子扔到其他鸟的鸟巢中去了。

但有时候,这些布谷鸟蛋会被被寄宿的鸟妈妈发现,然后就被抛弃;有时候,这些宿主会直接放弃整个鸟巢寻找新住处。然而道高一尺魔高一丈,有些品种的布谷鸟生下来的布谷鸟蛋的颜色和被寄宿的鸟的鸟蛋颜色很像,并且布谷鸟的破壳时间往往比宿主的鸟蛋早,小布谷鸟破壳后会将一些鸟蛋扔出鸟巢以获得更多的食物,小布谷鸟还能模拟宿主鸟孩子的叫声来骗取更多的食物!

简单来说,就是如何更高效地去骗吃骗喝

5.2原理

最简单的布谷鸟哈希结构是一维数组结构,会有 两个 hash 算法 将新来的元素映射到数组的两个位置。

  • 如果两个位置中有一个位置为空,那么就可以将元素直接放进去。‘

  • 但是如果这两个位置都满了,它就不得不「鸠占鹊巢」,随机踢走一个,然后自己霸占了这个位置。

    踢走的那个再经过哈希,找到数组的两个位置,以此类推

5.2.1演示步骤

(1)保存元素(两个位置均为空)

新来的元素a经过hash会落在(A2,B1)的位置,由于A2还没有元素,a直接落入A2

img

(2)保存元素(其中一个位置被占)

新插入元素b的hash会落在(A2,B3),由于A2已经被a占了,所以b会落在b3

img

(3)保存元素(两个位置都被占)

新来元素c的hash为(A2,B3), 由于两个位置都已经被占,它会随机将一个元素挤走,这里挤走了a

img

(4)被挤掉的元素重新找位置

a会重新进行hash,找到还未被占的B1位置

img

从上面可以看出,布谷鸟哈希算法会==帮这些受害者(被挤走的蛋)寻找其它的窝==。因为每一个元素都可以放在两个位置,只要任意一个有空位置,就可以塞进去。所以这个伤心的被挤走的蛋会看看自己的另一个位置有没有空,如果空了,自己挪过去也就皆大欢喜了。

但是如果这个位置也被别人占了呢?好,那么它也会再来一次「鸠占鹊巢」,把别人赶走。然后这个新的受害者还会重复这个过程直到所有的蛋都找到了自己的巢为止。

5.2.2问题

如果数组太拥挤了,连续踢来踢去几百次还没有停下来,这时候会严重影响插入效率。这时候布谷鸟哈希会设置一个阈值,当连续占巢行为超出了某个阈值,就认为这个数组已经几乎满了。这时候就需要对它进行扩容,重新放置所有元素

还会有另一个问题,那就是可能会存在==挤兑循环。比如两个不同的元素,hash 之后的两个位置正好相同,这时候它们一人一个位置没有问题。但是这时候来了第三个元素,它 hash 之后的位置也和它们一样,很明显,这时候会出现挤兑的循环==。

不过让三个不同的元素经过两次 hash 后位置还一样,这样的概率并不是很高,除非你的 hash 算法太挫了。

出现挤兑循环时,布谷鸟过滤器认为数组太拥挤了,会进行扩容,重新计算每个指纹的位置

5.2.4布谷鸟过滤器

(1)原理简述

布谷鸟过滤器和布谷鸟哈希结构一样,它也是一维数组,但是不同于布谷鸟哈希的是, 布谷鸟哈希会存储整个元素

而布谷鸟过滤器中 只会存储元素的指纹信息(几个bit,类似于布隆过滤器),过滤器牺牲了数据的精确性换取了空间效率。

布谷鸟过滤器还是只会选用两个 hash 函数,但是每个位置可以放置多个座位。这两个 hash 函数选择的比较特殊,因为过滤器中只能存储指纹信息。当这个位置上的指纹被挤兑之后,它需要计算出另一个对偶位置,计算这个对偶位置是需要元素本身的。

  1. 下面将探讨布谷鸟哈希和布谷鸟过滤器计算位置的公式的区别
  • 布谷鸟哈希:哈希位置计算公式

    1. fp = fingerprint(x) :表示对元素 x 计算其指纹(fingerprint),用来标识该元素在哈希表中的位置。指纹通常是一个固定长度的==比特串,用于唯一标识元素==,以便在哈希表中进行查找和定位
    2. p1 = hash1(x) % l:表示通过第一个哈希函数 hash1 对元素 x 进行哈希运算,并将结果对哈希表的大小 l 取模,得到元素 x 在哈希表中的第一个位置 p1。这个位置通常用于存放元素 x,如果该位置已经被占用,则可能会触发后续的再哈希操作。
    3. p2 = hash2(x) % l:表示通过第二个哈希函数 hash2 对元素 x 进行哈希运算,并将结果对哈希表的大小 l 取模,得到元素 x 在哈希表中的第二个位置 p2。这个位置通常用于作为备用位置,当元素 x 插入到第一个位置失败时,可以尝试插入到第二个位置
fp = fingerprint(x)		
p1 = hash1(x) % l
p2 = hash2(x) % l

知道了 p1 和 x 的指纹,是没办法直接计算出 p2 的。

  • 布谷鸟过滤器哈希:一个独特的 hash 函数,可以根据 p1 和 元素指纹 直接计算出 p2,而不需要完整的 x 元素

    1. fp = fingerprint(x):首先计算元素 x 的指纹(fingerprint),这个指纹通常是一个固定长度的比特串,用于标识元素在布谷鸟过滤器中的位置。
    2. p1 = hash(x):然后,对元素 x 进行哈希运算得到第一个哈希位置 p1。由于布谷鸟过滤器不需要将哈希值对数组大小取模,所以可以直接使用 hash(x) 得到的哈希值作为位置。
    3. p2 = p1 ^ hash(fp):接着,通过对 p1hash(fp) 进行异或运算,得到第二个哈希位置 p2。这个异或运算的结果即为第二个哈希位置,而不需要再进行取模操作。
fp = fingerprint(x)
p1 = hash(x)
p2 = p1 ^ hash(fp)  // 异或

从上面的公式中可以看出,知道 fp 和 p1,可以算出 p2

同样如果我们知道 p2 和 fp,也可以直接算出 p1 —— 对偶性

p1 = p2 ^ hash(fp)

所以不需要知道当前的位置是 p1 还是 p2,只需要将当前的位置和 hash(fp) 进行异或计算就可以得到对偶位置。只需要确保 hash(fp) != 0 就可以确保 p1 != p2,就不会出现自己踢自己导致死循环的问题。

为什么这里的 hash 函数不需要对数组的长度取模呢?

实际上是需要的,但是布谷鸟过滤器强制数组的长度必须是 2 的指数,所以对数组的长度取模等价于取 hash 值的最后 n 位。

在进行异或运算时,忽略掉低 n 位 之外的其它位就行。将计算出来的位置 p 保留低 n 位就是最终的对偶位置。

(2)组成

布谷鸟过滤器由一个数组组成,数组中每个元素大小为4个字节,可以存储4个指纹,每个指纹占一个字节(2^8 = 256种)。这样有以下两个好处:

  1. 避免出现hash后的位置一致而导致的循环挤兑的情况。
    这样即使两个元素被 hash 在了同一个位置,也不必立即「鸠占鹊巢」,因为这里有4个座位,你可以随意坐一个。除非这多个座位都被占了,才需要进行挤兑。这会显著降低挤兑次数。
  2. 同一个位置上的多个座位在内存空间上是连续的,可以有效利用 CPU 高速缓存。
(3)插入

初始化一个给定容量的过滤器Filter,这个容量数为2的n次方,如果不为2的n次方,内部会通将其转化为2的n次方

先进行一次hash,得出应当插入位置和应当插入的。

如果这个位置(bucket内的4个位置均被占用)插入失败,会进行第二次hash,查看第二个位置能否插入。若第二个位置插入失败,则会随机在两个位置挑选一个将其中的一个值标记为旧值,用新值覆盖旧值,旧值会在重复上面的步骤进行插入

会对插入的值进行校验,只有当未插入过该值时才会插入成功,若过滤器中已经存在该值,会插入失败返回false。

(4)扩容

如果数组过小,会发生循环挤兑的情况,如果超过最大挤兑次数,进行扩容,重新计算每个指纹的位置。

(5)查找

用两个hash函数计算,将计算结果与两个元素中的8个位置的指纹进行对比,如果对比成功则表示数据存在。先进行一次hash查询数据,若没有该值会进行第二次hash进行查询,若还是没有会返回false。

(6)删除

通过两次hash找到索引位置,若有该数据,将该位置数据删除。因为每个对象的指纹会存储到一个位置中,所以可以通过删除这个指纹来删除数据。

删除功能无法使用的情况:如果相同对象存储超过8个,就无法使用删除功能;如果俩数据的哈希值和指纹相同时,会出现误删除情况。

(7)删除全部

布谷鸟过滤器可以删除全部元素(重置数组为0)

(8)更新

删除后再添加新指纹。

5.3优缺点

5.3.1优点

  1. 支持新增和 删除元素
    1. 布隆过滤器不支持删除元素
  2. 更节省空间
    1. 布谷鸟哈希表更加紧凑
    2. 布谷鸟过滤器在错误率小于3%的时候空间性能是优于布隆过滤器
    3. 布谷鸟过滤器比布隆过滤器空间节省40%多
  3. 查询效率很高
    1. 布谷鸟过滤器只需一次哈希
    2. 布隆过滤器要采用多种哈希函数进行多次哈希

5.3.2缺点

  1. 插入性能较差
    1. 布谷鸟过滤器在计算哈希后可能当前位置上已经存储了指纹,这时就要将已存储的项踢到候选桶,随着桶越来越满,产生冲突的可能性越来越大,插入耗时越来越高
    2. 布隆过滤器插入时计算好哈希直接写入位即可
  2. 插入重复元素存在上限
    1. 布谷鸟过滤器对已存在的值会做踢出操作,因此重复元素的插入存在上限。
    2. 布隆过滤器在插入重复元素时并没有影响,只是对已存在的位再置一遍。
  3. 空间大小
    1. 布谷鸟过滤器必须是2的指数。
    2. 布隆过滤器不需要2的指数。
  4. 删除问题
    1. 有上述重复插入的限制,删除时也会出现相关的问题:
      1. 删除仅在相同哈希值被插入一次时是完美的
      2. 如果元素没有插入便进行删除,可能会出现误删除,这和假阳性率的原因相同
      3. 如果元素插入了多次,那么每次删除仅会删除一个值,你需要知道元素插入了多少次才能删除干净,或者循环运行删除直到删除失败为止

5.4代码实现

目前没有很完善的java实现,可以参考如下项目:

  • Redis布谷鸟过滤器:https://github.com/kristoff-it/redis-cuckoofilter

  • Redis通过插件支持sql及布谷鸟过滤器:https://github.com/RedBeardLab/rediSQL

5.5总结

Redis系列第五篇主要介绍了布谷鸟过滤器的起源(核心思想:更高效地去骗吃骗喝)、原理(两个hash位置)、演示步骤,以及布谷鸟过滤器计算两个hash位置的公式,区分布谷鸟哈希,最后总结了布谷鸟过滤器的优缺点。

在这里插入图片描述

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

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

相关文章

Linux小项目:在线词典开发

在线词典介绍 流程图如下: 项目的功能介绍 在线英英词典项目功能描述用户注册和登录验证服务器端将用户信息和历史记录保存在数据中。客户端输入用户和密码,服务器端在数据库中查找、匹配,返回结果单词在线翻译根据客户端输入输入的单词在字…

轻松玩转Git

轻松玩转Git 快速入门什么是Git为什么要做版本控制安装git Git实战单枪匹马开始干拓展新功能小结 紧急修复bug分支紧急修复bug方案命令总结工作流 上传GitHub第一天上班前在家上传代码初次在公司新电脑下载代码下班回到家继续写代码到公司继续开发在公司约妹子忘记提交代码回家…

CDH6.3.1离线安装

一、从官方文档整体认识CDH 官方文档地址如下: CDH Overview | 6.3.x | Cloudera Documentation CDH是Apache Hadoop和相关项目中最完整、测试最全面、最受欢迎的发行版。CDH提供Hadoop的核心元素、可扩展存储和分布式计算,以及基于Web的用户界面和重…

蓝桥杯备战刷题three(自用)

1.合法日期 #include <iostream> #include <map> #include <string> using namespace std; int main() {map<string,int>mp;int days[13]{0,31,28,31,30,31,30,31,31,30,31,30,31};for(int i1;i<12;i){for(int j1;j<days[i];j){string sto_strin…

Vivado Vitis 2023.2 环境配置 Git TCL工程管理 MicroBlaze和HLS点灯测试

文章目录 本篇概要Vivado Vitis 环境搭建Vivado 免费标准版 vs 企业版Vivado Windows 安装Vivado 安装更新 Vivado 工程操作GUI 创建工程打开已有工程从已有工程创建, 重命名工程GUI导出TCL, TCL复原工程TCL命令 Vivado 版本控制BlinkTcl脚本新建导出重建工程纯Verilog BlinkTc…

[CISCN2019 华北赛区 Day2 Web1]Hack World 1 题目分析与详解

一、分析判断 进入靶机&#xff0c;主页面如图&#xff1a; 主页面提供给我们一条关键信息&#xff1a; flag值在 表flag 中的 flag列 中。 接着我们尝试输入不同的id&#xff0c;情况分别如图&#xff1a; 当id1时&#xff1a; 当id2时&#xff1a; 当id3时&#xff1a; 我…

YOLOv8改进涨点,添加GSConv+Slim Neck,有效提升目标检测效果,代码改进(超详细)

目录 摘要 主要想法 GSConv GSConv代码实现 slim-neck slim-neck代码实现 yaml文件 完整代码分享 总结 摘要 目标检测是计算机视觉中重要的下游任务。对于车载边缘计算平台来说&#xff0c;巨大的模型很难达到实时检测的要求。而且&#xff0c;由大量深度可分离卷积层构…

C++:常量表达式

C11开始constexpr作为一种声明&#xff0c;为编译器提供了在编译期间确认结果的优化建议&#xff0c;满足部分编译期特性的需求 constexpr和const区别 int b10; const int ab; //运行成功 constexpr int cb; //编译器报错&#xff0c;b的值在编译期间不能确定 const int size1…

面试笔记系列二之java基础+集合知识点整理及常见面试题

目录 Java面向对象有哪些特征&#xff0c;如何应用 Java基本数据类型及所占字节 Java中重写和重载有哪些区别 jdk1.8的新特性有哪些 内部类 1. 成员内部类&#xff08;Member Inner Class&#xff09;&#xff1a; 2. 静态内部类&#xff08;Static Nested Class&#…

Vue 组件和插件:探索细节与差异

查看本专栏目录 关于作者 还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#x…

Linux查看进程占用句柄

ps -ef |grep python # 查找工具执行PID python pid 11287lsof -p 11287 |wc -l 查看进程占用句柄设置句柄上限IOError: [Errno 24] Too many open files:解决方法

阿里云短信验证笔记

1.了解阿里云的权限操作 进入AccessKey管理 选择子用户 创建用户组和用户 先创建用户组&#xff0c;建好再进行权限分配 添加短信管理权限 创建用户 创建好后的id和密码在此处下载可以得到 2.开通阿里云短信服务 进行申请&#xff0c;配置短信模板 阿里云短信API文档 短信服务…

逆向案例三:动态xhr包中AES解密的一般步骤,以精灵数据为例

补充知识&#xff1a;进行AES解密需要知道四个关键字&#xff0c;即密钥key,向量iv,模式mode,填充方式pad 一般网页AES都是16位的&#xff0c;m3u8视频加密一般是AES-128格式 网页链接:https://www.jinglingshuju.com/articles 进行抓包结果返回的是密文&#xff1a; 一般思…

【算法大家庭】分治算法

目录 &#x1f953;1.简单介绍 &#x1f9c8;2.汉诺塔问题 1.简单介绍 分治算法是解决问题的一种思想&#xff0c;它将一个大问题分解成若干个小问题&#xff0c;然后分别解决这些小问题&#xff0c;最后将小问题的解合并起来得到原问题的解。 分解&#xff1a;将原问题分解…

Mazing官方 2.17.17版新i功能介绍

iMazing官方 2.17.17版是一款管理苹果设备的软件&#xff0c;是一款帮助用户管理 IOS 手机的PC端应用程序&#xff0c;能力远超 iTunes 提供的终极 iOS 设备管理器。在iMazing官方版上与苹果设备连接后&#xff0c;可以轻松传输文件&#xff0c;浏览保存信息等&#xff0c;功能…

SD-WAN对云服务的影响

近年来&#xff0c;随着企业对云服务的依赖不断增加&#xff0c;SD-WAN技术成为提升连接性能的热门选择。SD-WAN通过简化云集成和连接&#xff0c;以及提升应用程序性能&#xff0c;为企业带来显著的业务优势。这种云连接的改进使企业能够更轻松地接触全球劳动力和潜在客户。 首…

语文专刊《中学语文》是什么级别的刊物?

语文专刊《中学语文》是什么级别的刊物&#xff1f; 《中学语文》创刊于1958年&#xff0c;由国家新闻出版总署批准&#xff0c;经湖北省教育厅主管的省级学术期刊。 《中学语文》是由湖北大学文学院主办、国内外公开发行的学术期刊&#xff0c;主要面向中学语文教师和语文教…

盘点:好用的伪原创文章生成器软件

伪原创文章生成器软件在内容创作域领应用的非常广泛&#xff0c;它不仅可以为创作人员解决文章或文案创作困难的问题&#xff0c;同时还可以作为提升创作效率的完美工作&#xff0c;然而随着互联网技术的发展&#xff0c;互联网上的伪原创文章生成器软件多到让人应接不暇&#…

echarts鼠标事件

鼠标事件支持方法 ECharts 支持常规的鼠标事件类型&#xff0c;包括 ‘click’、 ‘dblclick’、 ‘mousedown’、 ‘mousemove’、 ‘mouseup’、 ‘mouseover’、 ‘mouseout’、 ‘globalout’、 ‘contextmenu’ 事件 简单实例 // 基于准备好的dom&#xff0c;初始化EChar…

加州大学圣地亚哥分校伯克利分校联合英伟达最新开源!COLMAP-Free 3D Gaussian Splatting

作者&#xff1a;石昊 | 来源&#xff1a;3DCV 在公众号「3DCV」后台&#xff0c;回复「原论文」可获取论文pdf 添加微信&#xff1a;dddvision&#xff0c;备注&#xff1a;3D高斯&#xff0c;拉你入群。文末附行业细分群 从图像序列中进行相机姿态估计和新视角合成的问题。…