首页 > 其他分享 >一致性哈希

一致性哈希

时间:2024-04-06 22:22:06浏览次数:22  
标签:环上 映射 算法 哈希 一致性 节点

一致性哈希

   一、什么是一致性哈希
    一致性哈希是一种用于分布式系统中数据分片和负载均衡的算法。它的核心思想是将数据和节点通过哈希函数映射到一个固定范围的环形空间中,每个节点在环上占据一个位置,而数据则根据哈希函数计算出的值映射到环上的某个位置上。目前主要应用于分布式缓存当中。

    可以有效地解决分布式存储结构下动态增加和删除节点所带来的问题。

   二、普通哈希的问题

    1.  负载均衡

    分布式集群中,对机器的添加删除,或者机器故障后自动脱离集群这些操作是集群管理最基本的功能。如果采用常用的hash(object)%N 取模的方式,在节点进行添加或者删除后,需要重新进行迁移改变映射关系,否则可能导致原有的数据无法找到。

    比如:随着业务和流量的增加,假如我们的Redis查询服务节点扩展到了3个,为了将查询请求进行均衡,每次请求都在相同的Redis中,使用hv = hash(key) % 3的方式计算,对每次查询请求都通过hash值计算,得出来0、1 、2的值分别对应服务节点的编号,计算得到的hv的值就去对应的节点处理。

    但是这里有个问题,服务增减是需要对此时的key进行重新计算,比如减少一个服务的时候,此时需要按 hv = hash(key) % 2计算,而增加一个服务节点的时候需要按 hv = hash(key) % 4计算,而这种取模基数的变化会改变大部分原来的映射关系,导致数据查询不到。

    也就是说在对系统做扩容或者缩容时,必须迁移改变了映射关系的数据,否则会出现查询不到数据的问题。

    我们应该要重新想一个新的算法,来避免分布式系统在扩容或者缩容时,发生过多的数据迁移。而一致性哈希算法显然是一个更好选择!

    三、一致性哈希算法

    一致性哈希算法就很好地解决了分布式系统在扩容或者缩容时,发生过多的数据迁移的问题。一致性哈希同样使用了取模的方式,不同的是对 2^32 这个固定的值进行取模运算。

   1. 哈希环

   首先,我们把全量的缓存空间当做一个环形存储结构。环形空间总共分成2^32个缓存区。通过对 2^32 进行取模运算的结果值虚拟成一个圆环,环上的刻度对应一个 0~2^32 - 1 之间的数值。如下图:

         

 

   1) 节点入环

   一致性哈希要进行两步哈希:

   第一步:对存储节点进行哈希计算,也就是对存储节点做哈希映射,比如根据节点的 IP 地址进行哈希;

   第二步:当对数据进行存储或访问时,对数据进行哈希映射;

   所以,一致性哈希是指将「存储节点」和「数据」都映射到一个首尾相连的哈希环上。

   2) 新增节点

   当缓存集群的节点有所增加的时候,普通哈希算法会导致原有哈希映射大面积失效。而一致性哈希整个环形空间的映射仍然会保持顺时针规则,只有一小部分key的归属会受到影响。

3) 删除节点


2. 对「数据」进行哈希映射得到的结果要怎么找到存储该数据的「节点」呢?

映射的结果值往顺时针的方向的找到第一个节点,就是存储该数据的节点。

因此,在一致哈希算法中,如果增加或者移除一个节点,仅影响该节点在哈希环上顺时针相邻的后继节点,其它数据也不会受到影响。


3. 不平衡
我们通过新增节点和删除节点,知道了该方式会影响该节点的顺时针的后一个节点,其他节点不受影响。

但是因为生成哈希值的分布并不是均匀的,如下图新增k4、k5,如果节点B宕机了,k2和k4也迁移到节点C,导致那么大部分请求就落到节点C了,如果数量更多呢,此时会导致节点C压力陡增,这样就不均衡了!


4. 如何通过虚拟节点提高均衡度?

要想解决节点在哈希环上分配不均匀的问题,就是要有大量的节点,节点数越多,哈希环上的节点分布的就越均匀。

但问题是,实际中我们没有那么多节点。为了优化这种节点太少而产生的不均衡情况,一致性哈希算法引入了[虚拟节点]的概念。也就是对一个真实节点做多个副本。

具体做法是,不再将真实节点映射到哈希环上,而是将虚拟节点映射到哈希环上,并将虚拟节点映射到实际节点,所以这里有「两层」映射关系。

比如对每个节点分别设置 3 个虚拟节点:

对节点 A 加上编号来作为虚拟节点:A-01、A-02、A-03
对节点 B 加上编号来作为虚拟节点:B-01、B-02、B-03
对节点 C 加上编号来作为虚拟节点:C-01、C-02、C-03

 

 

五、为什么一致性哈希算法更多地应用在分布式缓存

由于分布式缓存系统的节点部署变化更频繁,而传统关系型数据库的分库分表相对稳定。不过说到mysq1,在水平分库分表的过程中, 仍然可以采用一致性哈希的思想。虽然这样的处理逻辑会复杂一些,却可以避免动态水平扩展时候的问题。

 

标签:环上,映射,算法,哈希,一致性,节点
From: https://www.cnblogs.com/hld123/p/18118039

相关文章

  • P3396 哈希冲突
    原题链接题解正常暴力解法如下:#include<bits/stdc++.h>usingnamespacestd;inta[150007];intmain(){intn,m;cin>>n>>m;for(inti=1;i<=n;i++)cin>>a[i];while(m--){charop;cin>>op;i......
  • c++算法学习笔记 (20) 哈希表
    1.模拟散列表//拉链法#include<bits/stdc++.h>usingnamespacestd;constintN=100003;inth[N];inte[N],ne[N],idx;//存链voidinsert(intx){intk=(x%N+N)%N;//让负数的余数变成正数(若直接加N,则可能溢出)e[idx]=x;ne[idx]......
  • 有关哈希表算法
    例题一解法(哈希表):算法思路:•如果我们可以事先将「数组内的元素」和「下标」绑定在⼀起存⼊「哈希表」中,然后直接在哈希表中查找每⼀个元素的target-nums[i],就能快速的找到「⽬标和的下标」。•这⾥有⼀个⼩技巧,我们可以不⽤将元素全部放⼊到哈希表之后......
  • LeetCode-142. 环形链表 II【哈希表 链表 双指针】
    LeetCode-142.环形链表II【哈希表链表双指针】题目描述:解题思路一:快慢指针判断是否有环见解题思路二:set()解题思路三:0题目描述:给定一个链表的头节点head,返回链表开始入环的第一个节点。如果链表无环,则返回null。如果链表中有某个节点,可以通过连续跟踪next......
  • 算法 哈希表 day03
    哈希表当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。牺牲了空间换取了时间当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构。数组set(集合)map(映射)第一题:242.有效的字母异位词-力扣(LeetCode)//暴力publicstaticboo......
  • LeetCode-146. LRU 缓存【设计 哈希表 链表 双向链表】
    LeetCode-146.LRU缓存【设计哈希表链表双向链表】题目描述:解题思路一:双向链表,函数get和put必须以O(1)的平均时间复杂度运行。一张图:解题思路二:0解题思路三:0题目描述:请你设计并实现一个满足LRU(最近最少使用)缓存约束的数据结构。实现LRUCache类:LR......
  • 基于donetcore/CAP实现分布式事务一致性
    官网:https://cap.dotnetcore.xyz相关介绍CAP是一个EventBus,同时也是一个在微服务或者SOA系统中解决分布式事务问题的一个框架。它有助于创建可扩展,可靠并且易于更改的微服务系统。在微软的 eShop 微服务示例项目中,推荐使用CAP作为生产环境可用的EventBus。什么是Event......
  • KMP&&哈希算法
    KMP算法KMP算法是一种字符串匹配算法,用于匹配模式串P在文本串S中出现的所有位置。例如S=“ababac”,P="aba",那么出现的所有位置是13KMP算法将原本O(n^2)的字符串匹配算法优化到了O(n),其精髓在于next数组,next数组表示此时模式串下标失配时应该移动到的位置,(每次下标失配时,就是i!......
  • 【Redis教程0x0C】数据库与缓存的一致性保证
    1.引言当我们在实现业务的过程中,如果发现服务器的性能瓶颈在数据库时,就要考虑加上Redis,让它作为数据库的缓存了。这样,客户端请求数据时,如果能在缓存命中,就不用去查数据库了,这大大减轻了数据库的压力,提高了服务器性能。那么这里就产生了个问题,我们在数据更新的时候,既需要......
  • 高并发下的数据一致性保障(图文全面总结)
    1背景我们之前介绍过分布式事务的解决方案,参考作者这篇《五种分布式事务解决方案(图文总结)》。在那篇文章中我们介绍了分布式场景下困扰我们的3个核心需求(CAP):一致性、可用性、分区容错性,以及在实际场景中的业务折衷。1、一致性(Consistency):再分布,所有实例节点同一时间看到是相......