海量数据去重的hash,布隆过滤器Bloom Filter,一致性hash

文章目录

  • 一、⭐hash函数
    • 如何选取hash函数?
    • 冲突处理
  • 二、⭐海量数据去重布隆过滤器
    • **布隆过滤器介绍**
    • 布隆过滤如何应用
  • 三、⭐一致性哈希
    • 基本原理:
  • 四、⭐一道面试题


一、⭐hash函数

hash函数的作⽤:避免插⼊的时候字符串的⽐较,hash函数计算出来的值通过对数组⻓度的取模能随机分布在数组当中。
  
  hash冲突(hash碰撞):hash(key)=addr,hash 函数可能会把两个或两个以上的不同 key 映射到同一地址。hash函数⼀般返回的是64位整数,将多个⼤数映射到⼀个⼩数组中,必然会产⽣冲突。
  
  负载因子:用来形容散列表的存储密度。数组存储元素的个数 / 数据长度;负载因子越小,冲突越小,负载因子越大,冲突越大。

如何选取hash函数?

选取计算速度快
强随机分布(等概率、均匀地分布在整个地址空间)
murmurhash1,murmurhash2,murmurhash3,siphash(redis6.0当中使⽤,rust等大多数语言选用的hash算法来实现hashmap),cityhash 都具备强随机分布性

siphash 主要解决字符串接近的强随机分布性,所以如果要hash字符串的话,优先选用siphash

冲突处理

链表法
  引用链表来处理哈希冲突,也就是将冲突元素用链表链接起来,这也是常用的处理冲突的⽅式。但是可能出现一种极端情况,冲突元素比较多,该冲突链表过长,这个时候可以将这个链表转换为红黑树。由原来链表时间复杂度 转换为红黑树时间复杂度 ,那么判断该链表过长的依据是多少?可以采⽤超过 256(经验值)个节点的时候将链表结构转换为红黑树结构。
  
开放寻址法
  将所有的元素都存放在哈希表的数组中,不使用额外的数据结构;一般使用线性探查的思路解决

  1. 当插⼊新元素的时,使⽤哈希函数在哈希表中定位元素位置
  2. 检查数组中该槽位索引是否存在元素。如果该槽位为空,则插⼊,否则3
  3. 在 2 检测的槽位索引上加⼀定步⻓接着检查2

这两种都会导致同类hash聚集,也就是近似值它的hash值也近似。那么它的数组槽位也靠近,形成hash聚集。第⼀种同类聚集冲突在前,第⼆种只是将聚集冲突延后。

可以使⽤双重哈希来解决上⾯出现hash聚集现象

二、⭐海量数据去重布隆过滤器

红⿊树和hashtable都不能解决海量数据问题,它们都需要存储具体字符串,如果数据量⼤,提供不了⼏百G的内存;所以需要尝试探寻不存储key的⽅案,并且拥有hashtable的优点(不需要⽐较字符串)。而布隆过滤器就刚好满足这一需求,它不需要存储具体字符串,也不需要比较。时间和空间复杂度都低。

布隆过滤器介绍

布隆过滤器定义:布隆过滤器是⼀种概率型数据结构,它的特点是⾼效的插⼊和查询,能明确告知某个字符串⼀定不存在或者可能存在

优缺点:布隆过滤器相⽐传统的查询结构(例如:hash,set,map等数据结构)更加⾼效,占⽤空间更⼩,但是确定是它返回的结果是概率性的,结果存在一定的误差,误差可控,同时不支持删除操作

构成:位图(bit数组)+ n个hash函数。

布隆过滤器原理
  当一个元素加入位图时:通过 K 个 hash 函数运算将这个元素映射到位图的 K 个点,并将它们置为1
  当检索一个元素时:通过通过 K 个 hash 函数运算检测位图的 K 个点是否都为1,如果都为1,则可能存在;如果有一个不为1,则一定不存在。
在这里插入图片描述
为什么不支持删除操作?因为在位图中每个槽位只有两种状态(0 或者 1),一个槽位被设置为 1 状态,但不确定它被设置了多少次;也就是不知道被多少个 key 哈希映射而来以及是被具体哪个 hash 函数映射而来,所以不支持删除操作。

如果想实现删除操作,可以用两个布隆过滤器,将删除的元素,放入第二个布隆过滤器里面,然后查询的时候去第二个里面查,如果第二个里面能查到说明可能被删除(注意也是存在误差的)。

布隆过滤如何应用

变量关系
  在实际应⽤过程中,布隆过滤器该如何使⽤?要选择多少个hash函数,要分配多少空间的位图,存储多少元素?另外如何控制假阳率(布隆过滤器能明确⼀定不存在,不能明确⼀定存在,那么存在的判断是有误差的,假阳率就是错误判断存在的概率)?

n - - 布隆过滤器中元素的个数,如上图 只有str1和str2 两个元素 那么 n=2。预取存储多少个值
p - - 假阳率,在0-1之间 0.0000001。能够接受的假阳率
m - - 位图所占空间
k - - hash函数的个数

选择k个hash函数
我们发现上面计算出需要30个hash函数,难道我们要去找30个不同的hash函数来吗,显然不该这样。我们应该选择一个 hash 函数,通过给 hash 传递不同的种子偏移值,采用线性探寻的方式构造多个 hash函数。

题外话,面试百度:hash 函数实现过程当中 为什么 会出现 i * 31?
i * 31 = i * (32-1) = i * (1<<5 -1) = i << 5 - i;
31 质数,hash 随机分布性很好

布隆过滤器应用场景

布隆过滤器通常用于判断某个 key 一定不存在的场景,同时允许判断存在时有误差的情况

常见处理场景:① 缓存穿透的解决;② 热 key 限流

缓存场景:为了减轻数据库的访问压力,在server和mysql之间加入缓存来存储热点数据

缓存穿透:server请求数据时,缓存和数据库都没有该数据,最终导致压力全部给到数据库

读取步骤:

先访问redis,如果存在则返回,不存在则 2
访问mysql,如过不存在则返回,存在则 3
将mysql的key写回redis
解决方案:

在redis设置<key,null>以此避免访问mysql,但是如果<key,null>过多会占用内存(可以设置过期时间解决这一问题)
在server端存储一个布隆过滤器,将mysql包含的key都放入布隆过滤器,布隆过滤器能过滤一定不存在的数据

三、⭐一致性哈希

一致性哈希(Consistent Hashing)是一种用于分布式系统的哈希算法,旨在解决由于节点动态增减导致的数据重分布问题。它通过将整个哈希值空间组织成一个环形结构,使得当节点发生变化时,只需重新分配少量的数据,从而提高系统的可扩展性和稳定性。

基本原理:

哈希环的构建: 将哈希函数的输出空间映射到一个逻辑环上,数值从 0 到 2³²-1(或其他范围),首尾相连形成一个环。

节点映射: 对每个节点(如服务器)进行哈希计算,将其映射到环上的某个点,这个点称为节点的哈希值。

数据映射: 对每个数据键进行哈希计算,也将其映射到环上的某个点。

数据存储规则: 数据被存储在从其哈希值顺时针方向遇到的第一个节点上。

优点:

减少数据迁移量: 当节点加入或离开时,只需重新定位受影响节点范围内的数据。

平衡负载: 通过引入虚拟节点,可以使数据和负载更均匀地分布在实际节点上。

高可扩展性和容错性: 系统可以平滑地添加或移除节点,而不会对整体造成重大影响。

虚拟节点

为了解决节点分布不均匀导致的数据倾斜问题,引入了虚拟节点的概念。每个实际节点对应多个虚拟节点,虚拟节点被映射到哈希环上,这样可以更均匀地分配数据。

应用场景:

分布式缓存系统: 如 Memcached 集群,通过一致性哈希来分配缓存键。

分布式存储系统: 如分布式文件系统,将文件块分配到不同的存储节点。

负载均衡: 动态地将请求分配到不同的服务器,提升系统的性能和可靠性。

四、⭐一道面试题

在这里插入图片描述
大文件hash拆成小文件
单台机器hash分流到多台机器


上一篇:在线生成论文的网站有哪些?分享5款AI一键原创论文免费网站


下一篇:基于FPGA的多路视频缓存