散列表

hash也可以叫做散列表,是由数组演化而来的,由keyvaluehash函数组成,也就是我们常说的key-value数据结构,通过函数f(key)计算出value存储的地址,最好的情况下可实现O(1)的时间复杂度,结构图大概如下

在上图中可以看出,一个key中不只存在了一个value,由此引出了一个概念,叫做冲突

如果f(key)指向的地址中有多个数据,那就需要继续对比,查找效率就很难确定了,所以解决冲突很有必要。

选择hash

hash函数有以下特点:

  • 计算速度快
  • 强随机分布(等概率、均匀地分布在整个地址空间)

现在常用的hash函数:murmurhash1,murmurhash2,murmurhash3,siphash ( redis6.0 当中使用,rust 等大多数语言选用的 hash 算法来实 现 hashmap),cityhash 都具备强随机分布性;其中siphash主要解决字符串接近的强随机分布性,如"100001","100002"。

负载因子

我们可以通过负载因子来形容散列表存储的密度

算法为:数组存储元素的个数 / key数组长度

可以看出负载因子越小,冲突概率越小,负载因子越大,冲突概率越大;.

冲突处理

链表法

引用链表来处理哈希冲突,也就是将冲突元素用链表链接起来,这也是常用的处理冲突的方式,如上图所示。单可能会出现一种极端情况,冲突元素过多,导致该链表过长,这时可以将链表转为查找效率更高的红黑树、最小堆,时间复杂度就由O(n)优化为O();至于何时转换,这就需要一个经验值去衡量。

开放寻址法

这种方法将所有的元素都存放在哈希表的数组中,不使用额外的数据结构,一般使用线性探查的思路解决

  1. 当插入新元素时,使用f(key)定位位置
  2. 检查定位地址中是否存在元素,如果槽位为空,插入
  3. 如果槽位不为空,则加一定的步长继续判断元素是否存在,直到找到一个空槽位,一般有以下几种:
  • i+1,i+2,i+3,...,i+n
  • i+1^2,i+2^2,i+3^2,...

但这种容易导致hash聚集,所以我们通常使用双重hash来避免,设置一个hash函数组,当hash1(key)槽位不为空,使用hash2(key)去寻址,以此类推,找到空槽位。

流程实现如下图所示:

动态扩容

在一个有限的空间里,在数据不断的增加下,不管在如何优化,总会有冲突的情况,所以还需要解决根本性的问题。由负载因子的计算公式可以看出,扩大key的数组长度可以很大程度缓解冲突的概率,我们可以设置一个负载因子的阀值,当超过这个阀值时,给数组扩容,把旧数组的数据拷贝到新的数组上,我们熟知的redis就有一个扩容和缩容的机制,这也是一个很有效解决冲突的方法。

布隆过滤器

布隆过滤器是一种概率型数据结构,它的特点是高效地插入和 查询,能确定某个字符串一定不存在或者可能存在; 布隆过滤器不存储具体数据,所以占用空间小,查询结果存在 误差,但是误差可控,同时不支持删除操作

构成

位图(BIT 数组)+ n 个 hash 函数

m % 2^n = m & ( 2^n - 1)

原理

当一个元素加入位图时,通过 k 个 hash 函数将这个元素映射到 位图的 k 个点,并把它们置为 1;当检索时,再通过 k 个 hash 函数运算检测位图的 k 个点是否都为 1;如果有不为 1 的点,那 么认为该 key 不存在;如果全部为 1,则可能存在;

为什么不支持删除操作?

  • 在位图中每个槽位只有两种状态(0 或者 1),一个槽位被 设置为 1 状态,但不确定它被设置了多少次;也就是不知道 被多少个 key 哈希映射而来以及是被具体哪个 hash 函数映 射而来;
  • 不存在 只要一个索引位为0;如果都为1,是否一定存在? 不一定,可控的(假阳率)

应用分析

在实际应用中,该选择多少个 hash 函数?要分配多少空间的位 图?预期存储多少元素?如何控制误差?

先看看以下四个变量的关系

  • n -- 布隆过滤器中的预期个数
  • p -- 假阳率,在0-1之间
  • m -- 位图大小
  • k -- hash函数的个数

公式如下:

在实际应用中一般只需要确定n和p,从而计算出合适的m和k可以在下面这个网站计算出合适的值

https://hur.st/bloomfilter

应用场景

布隆过滤器通常用于判断某个 key 一定不存在的场景,同时允 许判断存在时有误差的情况,这里我们最熟知的应用场景就是在解决redis的缓存穿透。

因为redis是在内存中缓存的数据,数据库是放在硬盘中的,内存的访问速度要比硬盘快的多,所以redis通常用来存放热点数据,减轻数据库的访问压力,当请求过来时优先查询redis数据,redis查询不到,在去查数据库中的数据。

当有黑客或者业务bug造成大量重复请求不存在的数据,压力就会全部涌向数据库,这就是我们常说的缓存击穿,这时在server端加上一个布隆过滤器,因为布隆过滤器能判断出一定不存在的数据,能拦截出大部分无效的请求,偶尔有误差的判断,也不会对服务造成压力。

hash与布隆过滤器相关推荐

  1. 海量数据去重,hash、布隆过滤器以及hyperloglog丨c/c++linux服务器开发丨后端开发丨Linux后台开发丨底层原理

    海量数据去重,hash.布隆过滤器以及hyperloglog 视频讲解如下,点击观看: 海量数据去重,hash.布隆过滤器以及hyperloglog丨c/c++linux服务器开发丨后端开发丨Linu ...

  2. 海量数据去重hash与布隆过滤器

    海量数据去重hash与布隆过滤器 背景 缓存穿透 需求 set和map unordered_map 总结 布隆过滤器 代码 背景 在使⽤word⽂档时,word如何判断某个单词是 否拼写正确? ⽹络爬 ...

  3. HBase的布隆过滤器详解

    HBase的布隆过滤器详解 1.布隆过滤器的简单介绍 2.布隆过滤器的原理分析 2.1 哈希表存在的问题 2.2 布隆过滤器的原理 2.2.1 原理详解 2.2.2 布隆过滤器失误率的调节 2.2.3 ...

  4. 布隆过滤器(Bloom Filter)详解——基于多hash的概率查找思想

    转自:http://www.cnblogs.com/haippy/archive/2012/07/13/2590351.html   布隆过滤器[1](Bloom Filter)是由布隆(Burton ...

  5. 关于布隆过滤器的所有信息:利用Hash实现的索引方案

    Table of Contents 什么是布隆过滤器? 关于布隆过滤器的所有信息 参考文献 什么是布隆过滤器? 布隆过滤器(Bloom Filter)是1970年由布隆提出的.它实际上是一个很长的二进 ...

  6. COSMIC的后端学习之路——1.3 海量数据去重的Hash与BloomFilter(布隆过滤器),bitmap(位图)

    1.3 海量数据去重的Hash与BloomFilter,bitmap 知识树 1.海量数据查找的应用场景 2.平衡二叉树 3.哪些算法涉及二分查找 4.散列表 (1)hash冲突 (2)负载因子 (3 ...

  7. Hash(哈希/散列)和Bloom Filter(布隆过滤器)

    文章目录 Hash(函数/表) Bloom Filter 布隆过滤器的误识别问题 总结 参考 Hash(函数/表) Hash (中译为哈希,或者散列)函数在计算机领域,尤其是数据快速查找领域,加密领域 ...

  8. Hash,位图,布隆过滤器

    文章目录 哈希概念 哈希冲突 哈希函数 除留余数法--(非常常用) 直接定址法--(常用) 平方取中法--(了解) 折叠法--(了解) 随机数法--(了解) 数学分析法--(了解 ) 哈希冲突解决 闭 ...

  9. Redis 预防缓存穿透“神器” — 布隆过滤器

    1. 布隆过滤器 1.1 概念 在架构设计时有一种最常见的设计被称为布隆过滤器,它可以有效减少缓存穿透的情况.其主旨是采用一个很长的二进制数组,通过一系列的 Hash 函数来确定该数据是否存在. 布隆 ...

最新文章

  1. 2018 区块链技术及应用峰会(BTA)·中国全日程新鲜出炉,更多精彩议题看不停
  2. VS中快速生成dll和lib方法
  3. nyoj 234 吃土豆
  4. Java01-day01【发展史、跨平台原理、JRE和JDK、常用DOS命令、关键字、常量、数据类型、变量使用的注意事项、标识符、类型转换】
  5. python文件写入字典格式输出_Python把对应格式的csv文件转换成字典类型存储脚本的方法...
  6. 在安装好python后文件显示还是应用程序_在djang中找不到已安装的应用程序
  7. (王道408考研数据结构)第五章树-第三节2:二叉树构造和重建
  8. c# xls 复制一行_C# 复制Excel单元格格式
  9. 《Ruby程序员修炼之道》(第2版)—第1章1.4节易用的Ruby工具和应用程序
  10. oracle连接中出现错误ORA-12541,ORA-12514,ORA-01017的解决方法
  11. 社保基金入市规模或达3000亿元
  12. OpenCV_cv::Mat的深拷贝 浅拷贝问题
  13. MMKV_MMKV - 由微信开发的高效,小巧的移动端key-value存储框架,适用于iOS和Android...
  14. SGX软硬件栈(四)——桥函数
  15. PostgreSQL中的索引—7(GIN)
  16. 代码主题darcula_Intellij idea 中的Darcula主题怎么把颜色改回来?
  17. ubuntu 18.04.2 server基本安装配置
  18. ultraedit许可证id 7位数字_优雅的数据库ID设计
  19. 玩转开发板--Linux系统移植至开发板fl2440实践过程
  20. Linux从头学05-系统启动过程中的几个神秘地址,你知道是什么意思吗?

热门文章

  1. 小型项目测试外包费用_报告:小型发布商看到有效每千次展示费用下降
  2. 不要让老实人吃亏...
  3. 1426:智力大冲浪
  4. 浅谈淘宝搜索排序算法【转自淘宝搜索博客】
  5. elementui 分页与tabe数据绑定
  6. 46 webpack优化- Scope Hoisting
  7. 《R语言实战笔记》第一章:R语言介绍
  8. 上不了岸的new grad,惨遭layoff的码农,都在抓这根“救命稻草”!
  9. 微信号复制跟跳转——execCommand()
  10. 【解决方案】报错:WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None))