Hash和BloomFilter

140 阅读5分钟

散列表

一、首先了解一下平衡二叉树

增删改查的时间复杂度为lognlogn。 平衡的目的是增删后,保证下次搜索能稳定排除一半的数据。比如:10亿个节点,最多比较30次。
总结: 通过比较保证有序,通过每次排除一半的元素达到快速索引的目的。

二、散列表

1、组成

①哈希函数
②数组

1.1、hash函数

①:冲突情况 :将两个或两个以上的不同key映射到同一地址。
②:映射函数:Hash(key)=addr; 所以它的作用就是完成映射关系。

1.1.1、选择hash(不需要看源码,明白怎么选择就行)
  • 计算速度快
  • 强随机分布 (等概率、均匀地分布整个地址空间)
  • siphash主要解决字符串接近的强随机分布
  • murmurhash2常用
  • cityhash常用
1.1.2、hash操作
  • 插入
  • 查找
1.1.3、hash负载因子
  • 数组存储元素的个数/数组长度。
  • 用来形容散列表的存储密度;
  • 负载因子越小,冲突越小,负载因子越大,冲突越大。
  • 主要描述冲突程度
1.1.4、hash冲突解决方案

方法一:拉链法 (链表法) 将具有相同的addr的key,可以用链表链接。
但是负载因子要在合理范围内。 image.png
方法二:开发寻址法

  • 将所有的数据直接存储在哈希数组中。如果冲突就采用某种算法来改变位置。
    算法有多种思路:
  • 比如 i+1,i+2,i+3等等 或者 i^1,i^2,i^3等等。
    但是他们会出现hash聚集,也就是近似值的hash值很接近,那么位置也接近。聚集的话,就会在一片区域内,查找,这片区域数据太多了,时间复杂从O(1)变O(n)。所以可以使用双重哈希解决。 但是负载因子要在合理范围内。

image.png

如果不在合理范围内
used:实际存储元素的个数。
方法一:扩容,used > size (避免冲突)
方法二:缩容:used < 0.1size (不能解决冲突) 操作扩容或缩容后,需要创建hash,因为算法会改变。类似顺序表的扩容操作。

2、STL中的散列表

2.1、STL中常使用的函数

unordered_map、unordered_multimap、 unordered_set,unordered_multiset这4个都是用的散列表

2.2、实现原理

image.png

image.png

三、布隆过滤器

1、背景(使用情况)

  • 只想知道key存在不存在,不想知道内容。

2、构成

位图和多个hash函数。
首先假设:它是由一个二进制构成的数组,里面存储0或1,所以保密性很好。然后假设有3个哈希函数来计算,数据要存储的数组下标,(不一定是3个哈希,这里只是举例,便于理解),经过3个哈希函数得到3个下标,将③个下标的数组标位1,说明存储好了。
但是如果我们要删除的话,就会出现问题。比如:hello和你好经过hash运算都要存储在下标2的位置。那么现在我们取出了hello,2的下标改为0,但是没取出你好,就会导致误以为删除了你好。

a、优点:
①具有安全性,存储的不是数据本身。
②保密性,只看得到0和1
③速度快,哈希计算
b、缺点
①删除容易误判,可以多用1个哈希来计算
②还有一种误判,如果存储的hello明明是用另一个位图计算,但是这个位图里,能确定它存在,就会导致误以为存在了。

3、应用分析

在实际应用中,需要但是个hash函数?要分配多少空间的位图?预期存储多少元素?如何控制误差?
可以使用该网站求以下内容,bloom计算

n:预期布隆过滤器中元素的个数。
p:可以失误的概率
m:位图所占的空间
k:hash函数的个数
公式如下:
n=ceil(m/(-k/log(1-exp(log(p)/k))))
p=pow(1-exp(-k/(m/n)),k)
m=ceil((n*log(p))/log(1/pow(2,log(2))))
k=round((m/n)*log(2));

4、分布式一致性哈希

1、哈希环

  • 将节点和数据通过哈希函数映射到一个固定的范围(通常是一个环)。
  • 节点和数据的位置由哈希值决定。

2、数据定位

  • 数据通过哈希函数映射到环上的某个位置。
  • 数据存储在顺时针方向找到的第一个节点上。

3、节点增减

  • 增加节点时,只有新节点到其前驱节点之间的数据需要迁移。
  • 删除节点时,只有被删除节点的数据需要迁移到其后继节点。

4、 哈希迁移

问题描述

在分布式缓存系统中,当节点增加或删除时,需要将部分数据从旧节点迁移到新节点。如果使用传统的哈希取模方法,节点的增减会导致大量数据重新映射,影响系统性能。

5、哈希偏移

在一致性哈希中,如果节点数量较少,可能会导致数据分布不均匀,某些节点负载过高,而其他节点负载较低。

5.1、虚拟节点的解决方案
  • 通过引入虚拟节点,将一个物理节点映射为多个虚拟节点,分散在哈希环上。
  • 虚拟节点的数量可以远大于物理节点的数量,从而使得数据分布更加均匀。
5.2、实现方式
  • 为每个物理节点生成多个虚拟节点,例如在节点 IP 和端口后加上虚拟编号(如 192.168.1.1:8080:1192.168.1.1:8080:2)。
  • 对虚拟节点进行哈希映射,数据定位时找到对应的虚拟节点,再映射到物理节点。
5.3、虚拟节点优点
数据分布均匀
  • 虚拟节点将物理节点的负载分散到哈希环的多个位置,避免数据倾斜。
动态扩容
  • 增加物理节点时,只需为其分配虚拟节点,数据迁移量较少
容错性
  • 删除物理节点时,其虚拟节点对应的数据会迁移到其他物理节点,系统仍然保持平衡。