一致性hash算法 - consistent hashing

2024-06-08 19:48

本文主要是介绍一致性hash算法 - consistent hashing,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  1、   情景分析

前一篇博文分析了HashMap源码,HashMap在许多场景中作为存储数据的不二选择。

 

但是否使用HashMap就能解决所有在空间和时间的均衡问题??

 

下面考虑使用HashMap的二个极端情景:

 

原来有 N 台Server,所有数据通过一种 hash 算法(以hash(key)%N为例)映射到 N 台Server 中。

 

情景一其中的 M 台服务器失效,那么需要将服务器 M 移除;或者访问量锐减,撤除 M 台服务器

 ,此时服务器的数量为 (N-M)台,最后,映射公式变成了 hash(key)%(N-M);

 

情景二由于访问量加大,需要添加 M 台Server ,这时候 Server 是 (N+M) 台,映射公式变成了 hash(key)%(N+M)。

 

    这两种情景看似只是数学公式上的小差别,但是对于 Server 和 Internet 来说是一个巨大的灾难。

海量的数据重新重新计算hash然后定位到不同的 Server 中,整个过程对Internet的占用也很严重。

这种情况是非常糟糕的。

 

    用专业的说法来总结上述问题:以上hash算法的问题在于容错性和扩展性不好。

所谓容错性是指当系统中某一个或几个服务器变得不可用时,整个系统是否可以正确高效运行;

而扩展性是指当加入新的服务器后,整个系统是否可以正确高效运行。

 

   一个设计良好的分布式哈希方案应该具有良好的单调性,即服务节点的增减不会造成大量哈希重定位。一致性哈希算法就是这样一种哈希方案。

 

 

2、    一致性哈希算法算法简述

    一致性哈希算法(Consistent Hashing)最早在论文《Consistent Hashing and Random Trees: Distributed Caching Protocols for Relieving Hot Spots on the World Wide Web》中被提出。简单来说,一致性哈希将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0 – 2^32-1(即哈希值是一个32位无符号整形),整个哈希空间环如下:



 

 

整个空间按顺时针方向组织。0和2^32-1在零点中方向重合。

 

    下一步将各个服务器使用Hash进行一个哈希,具体可以选择服务器的ip或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置。为了方便讨论,这里假设初始有三台 Server使用ip地址哈希后在环空间的位置如下:



 

    接下来使用如下算法定位数据访问到相应 Server:将数据key使用相同的函数 Hash 计算出哈希值h,通根据h确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器。该解决方案有点像Hash的开放寻址中的线性探测法解决hash冲突的策略。 

 

例如我们有A、B、C、D四个数据对象,经过哈希计算后,在环空间上的位置如下:



  

根据一致性哈希算法,数据A会被定为到Server 1上,D被定为到Server 3上,而B、C分别被定为到Server 2上。

 

3、    一致性哈希算法的容错性与可扩展性分析

    3.1、下面分析一致性哈希算法的容错性:现假设Server 3挂了(专业一点就是宕机):

 


  

    可以看到此时A、C、B不会受到影响,只有D节点被重定位到Server 2。一般的,在一致性哈希算法中,如果一台 Server 不可用,则受影响的数据仅仅是此 Server 到其环空间中前一台 Server(即顺着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。

 

  3.2、分析可拓展性:如果我们在系统中增加一台服务器Memcached Server 4




 
  

此时A、D、C不受影响,只有B需要重定位到新的Server 4。一般的,在一致性哈希算法中,如果增加一台 Server ,则受影响的数据仅仅是新 Server 到其环空间中前一台Server (即顺着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。

 

    综上所述,一致性哈希算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。

 

4、   虚拟节点

    一致性哈希算法在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜问题。例如我们的系统中有两台 server,其环分布如下:



  

    此时必然造成大量数据集中到Server 1上,而只有极少量会定位到Server 2上。为了解决这种数据倾斜问题,一致性哈希算法引入了虚拟节点机制,即对每一个服务节点计算多个哈希,每个计算结果位置都放置一个此服务节点,称为虚拟节点。

 

    具体做法可以在服务器ip或主机名的后面增加编号来实现。例如上面的情况,我们决定为每台服务器计算三个虚拟节点,于是可以分别计算“Memcached Server 1#1”、“Memcached Server 1#2”、“Memcached Server 1#3”、“Memcached Server 2#1”、“Memcached Server 2#2”、“Memcached Server 2#3”的哈希值,于是形成六个虚拟节点:



  

    同时数据定位算法不变,只是多了一步虚拟节点到实际节点的映射,例如定位到“Memcached Server 1#1”、“Memcached Server 1#2”、“Memcached Server 1#3”三个虚拟节点的数据均定位到Server 1上。这样就解决了服务节点少时数据倾斜的问题。在实际应用中,通常将虚拟节点数设置为32甚至更大,因此即使很少的服务节点也能做到相对均匀的数据分布,避免出现雪崩的情况。

 

5、  总结 

    在动态分布式缓存系统里哈希算法承担着系统架构上的关键点。 使用分布更合理的算法可以使得多个服务节点间的负载相对均衡,可以最大程度的避免资源的浪费以及服务器过载。 使用一致性哈希算法,可以最大程度的降低服务硬件环境变化带来的数据迁移代价和风险。 使用更合理的配置策略和算法可以使分布式缓存系统更加高效稳定。

  

简单的一致性哈希算法,可以使用MD5算法来作为hash算法, 对于各个hash算法的比较, 可以参考下面的讨论

http://www.iteye.com/topic/346682

 

参考资料地址:

http://blog.csdn.net/sparkliang/article/details/5279393

http://en.wikipedia.org/wiki/Consistent_hashing

http://www.jiacheo.org/blog/174

 

 

这篇关于一致性hash算法 - consistent hashing的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1043144

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

hdu1496(用hash思想统计数目)

作为一个刚学hash的孩子,感觉这道题目很不错,灵活的运用的数组的下标。 解题步骤:如果用常规方法解,那么时间复杂度为O(n^4),肯定会超时,然后参考了网上的解题方法,将等式分成两个部分,a*x1^2+b*x2^2和c*x3^2+d*x4^2, 各自作为数组的下标,如果两部分相加为0,则满足等式; 代码如下: #include<iostream>#include<algorithm

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

usaco 1.2 Milking Cows(类hash表)

第一种思路被卡了时间 到第二种思路的时候就觉得第一种思路太坑爹了 代码又长又臭还超时!! 第一种思路:我不知道为什么最后一组数据会被卡 超时超了0.2s左右 大概想法是 快排加一个遍历 先将开始时间按升序排好 然后开始遍历比较 1 若 下一个开始beg[i] 小于 tem_end 则说明本组数据与上组数据是在连续的一个区间 取max( ed[i],tem_end ) 2 反之 这个

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO