前言:对于一致性哈希已经不是罕见概念,在此只是对原有理论概念的一个整理和用自己的理解讲述,希望对新手有些许帮助,利人利己足矣。

1.概念

一致哈希是一种特殊的哈希算法。在使用一致哈希算法后,哈希表槽位数(大小)的改变平均只需要对 K/n 个关键字重新映射,其中 K是关键字的数量,n是槽位数量。然而在传统的哈希表中,添加或删除一个槽位的几乎需要对所有关键字进行重新映射。

一致哈希将每个对象映射到圆环边上的一个点,系统再将可用的节点机器映射到圆环的不同位置。查找某个对象对应的机器时,需要用一致哈希算法计算得到对象对应圆环边上位置,沿着圆环边上查找直到遇到某个节点机器,这台机器即为对象应该保存的位置。 当删除一台节点机器时,这台机器上保存的所有对象都要移动到下一台机器。添加一台机器到圆环边上某个点时,这个点的下一台机器需要将这个节点前对应的对象移动到新机器上。 更改对象在节点机器上的分布可以通过调整节点机器的位置来实现。

2.应用场景

在使用N台缓存服务器时,一种常用的负载均衡方式是,对资源Object的请求使用 Hash(Object)%N 来映射到某一台缓存服务器。但是缺点有二:

1.一个服务器(服务器A)Down掉之后,服务器A中的缓存资源都会失效,映射公式变成了Hash(Object)%(N-1), 缓存失效,这会使得缓存服务器大量集中地向原始内容服务器更新缓存。

2.当增加或减少一台缓存服务器时,映射公式变成了Hash(Object)%(N+1),这种方式可能会改变所有资源对应的Hash值,也就是所有的缓存都失效了,这会使得缓存服务器大量集中地向原始内容服务器更新缓存。

因些,需要一致哈希算法来避免这样的问题。 一致哈希尽可能使同一个资源映射到同一台缓存服务器。这种方式要求增加一台缓存服务器时,新的服务器尽量分担存储其他所有服务器的缓存资源。减少一台缓存服务器时,其他所有服务器也可以尽量分担存储它的缓存资源。 一致哈希算法的主要思想是将每个缓存服务器与一个或多个哈希值域区间关联起来,其中区间边界通过计算缓存服务器对应的哈希值来决定。(定义区间的哈希函数不一定和计算缓存服务器哈希值的函数相同,但是两个函数的返回值的范围需要匹配。)如果一个缓存服务器被移除,则它会从对应的区间会被并入到邻近的区间,其他的缓存服务器不需要任何改变。

3.原理简析

3.1环形Hash空间

考虑通常的Hash算法都是将value 映射到一个32位的 key 值上,也就是 0~2^32-1次方的数值空间。我们可以将这个空间想象成一个首( 0 )尾( 2^32-1 )相接的圆环,如下图1所示:

图1 环形Hash空间

3.2把对象映射到环形Hash空间

下面考虑 4 个资源对象 object1,object2,object3,bject4 ,通过 Hash 函数计算出的 Hash 值(key)在环上的分布如图 2 所示:

图2 资源对象的Key值分布

如此:

Key1 = Hash(Object1);

······

Key4 = Hash(Object4);

3.3把资源服务器映射到环形Hash空间

一致性Hash的基本思想就是将资源对象和缓存服务器(cache)都映射到同一个Hash数值空间中,并且使用相同的Hash算法。缓存服务器(cache)的Hash计算,一般的方法可以使用服务器(cache)机器的IP地址或者机器名作为Hash输入。

假设当前有 A,B 和 C 共 3 台缓存服务器(cache) ,那么其映射结果将如图 3 所示,他们在 hash 空间中,以对应的 hash值排列。

图3 服务器和资源对象的Key值分布

如此:

KeyA = Hash(CacheA);

······

KeyC = Hash(CacheC);

3.4把资源对象映射到缓存服务器

现在服务器(cache)和资源对象都已经通过同一个Hash算法映射到Hash数值空间中了,接下来要考虑的就是如何将对象映射到服务器(cache)上面。

在这个环形空间中,如果沿着顺时针方向从对象的 key 值出发,直到遇见一个服务器(cache),那么就将该对象存储在这个缓存服务器上,因为对象和服务器的Hash 值是固定的,因此这个服务器必然是唯一和确定的。这就是对象和服务器的映射方法。

依然继续上面的例子(参见图 3 ),那么根据上面的方法,对象 object1 将被存储到 cache A 上; object2和 object3 对应到 cache C ; object4 对应到 cache B ;

3.5考虑服务器的增减

根据上面的映射方法(顺时针寻找)我们可以很容易的想象服务器的增减导致资源对象映射的改变情况。如图4和5所示:

图4 缓存服务器B被移除后的映射改变

图5 添加缓存服务器D后的映射改变

根据上文所述,一致性哈希中节点的改变需要K/N个关键字的映射,N是缓存服务器个数,K是资源对象的个数,显然4/3和4/4取整都为1,与以上结果相符。

3.6采用虚拟节点保证平衡性

在分布式缓存中,都希望资源对象能够尽可能的均匀分布到缓存服务器中,这也是平衡性的要求。但是,一致性哈希并不能保证绝对的平衡性。举个例子,在服务器(cache)较少情况下,资源对象并不能被均匀的映射到服务器上,比如在上面的例

子中,仅部署 cache A 和 cache C 的情况下,在 4 个资源对象中, cache A 仅存储了 object1 ,而 cache C 则存储了 object2 、 object3 和 object4 。显然,分布是很不平衡的。

那么,为解决这种情况,一致性哈希引进了虚拟节点的概念。

虚拟节点( virtual node )是实际服务器节点在Hash空间中的一个或多个复制品(replica),一实际个节点对应了若干个“虚拟节点”,这个对应个数也就是“复制个数”,“虚拟节点”在Hash空间中以Hash值排列。

仍以仅部署 cache A 和 cache C 的情况为例,在图 4 中我们已经看到,cache节点分布并不均匀。现在我们引入虚拟节点,并设置“复制个数”为 2 ,这就意味着一共会存在 4 个“虚拟节点”, cache A1, cache A2 代表了cache A; cache C1, cache C2 代表了 cache C;假设一种比较理想的情况,如图6:

图6 引入虚拟节点后的映射关系

此时,资源对象到“虚拟节点”的映射关系为:objec1->cache A2 ; objec2->cache A1 ; objec3->cache C1 ; objec4->cache C2 ;因此对象 object1 和 object2 都被映射到了 cache A 上,而 object3 和 object4 映射到了 cache C 上;平衡性有了很大提高。

引入“虚拟节点”后,映射关系就从 { 对象 -> 节点 } 转换到了 { 对象 -> 虚拟节点 } 。查询物体所在 cache时的映射关系如图 7 所示:

图7 查询资源对象的计算过程

虚拟节点的Hash值计算可以采用对应节点的 IP 地址加数字后缀的方式。例如假设 cache A 的 IP 地址为202.168.14.241 。

引入虚拟节点前,计算 cache A 的 Hash 值:Hash(“202.168.14.241”);

引入虚拟节点后,计算虚拟节点cache A1 和的Hash值:Hash(“202.168.14.241#1”);

下面这个URL中讲的很详细:http://www.codeproject.com/Articles/56138/Consistent-hashing

4.C++实现

一致性哈希还必须解决两个问题,一个是用于节点存储和查找的数据结构的选择,另一个是Hash算法的选择。

我们可以想象,节点是均匀的分布在你一个圆环上,也就是说节点Hash值可以存储在一个有序队列上。同时,该数据结构应该高效地支持节点频繁的增删,和理想的查询效率,那么自然会想到红黑树,它是一颗近似平衡的二叉树,因为操作比如插入、删除和查找某个值的最坏情况时间都要求与树的高度成比例,这个在高度上的理论上限允许红黑树在最坏情况下都是高效的,而不同于普通的二叉查找树。因此,用于节点存储和查找的数据结构我们选择红黑树,并实现其插入、删除、查找功能,并增加一个lookup函数,用于查找key中最小的节点。

Hash算法的选择,一致性哈希很重要的一点就是为了解决负载均衡问题,而虚拟节点是负载均衡的关键,所以,我们希望虚拟节点可以均匀地散步在圆环上。这里我们选择MD5算法,通过MD5算法,可以将一个标识串(用于标示虚拟结点)进行转化,得到一个16字节的字符数组,再对该数组进行处理,得到一个整型的Hash值。由于MD5具有高度的离散性,所以生成的Hash值也会具有很大的离散性,会均匀地散列到“环”上。

百闻不如一见,实际代码链接:

http://files.cnblogs.com/coser/ConsistentHashAlgorithm.rar

5.PHP实现

下面是转自http://blog.csdn.net/mayongzhan/article/details/4298834的PHP实现:

一致性哈希(Consistent Hashing)的更多相关文章

  1. 深入一致性哈希(Consistent Hashing)算法原理,并附100行代码实现

    转自:https://my.oschina.net/yaohonv/blog/1610096 本文为实现分布式任务调度系统中用到的一些关键技术点分享——Consistent Hashing算法原理和J ...

  2. 一致性哈希(consistent hashing)算法

    文章同步发表在博主的网站朗度云,传输门:http://www.wolfbe.com/detail/201608/341.html 1.背景        我们都知道memcached服务器是不提供分布 ...

  3. 用于KV集群的一致性哈希Consistent Hashing机制

    KV集群的请求分发 假定N为后台服务节点数,当前台携带关键字key发起请求时,我们通常将key进行hash后采用模运算 hash(key)%N 来将请求分发到不同的节点上, 后台节点的增删会引起几乎所 ...

  4. 一致性hash算法Consistent Hashing

    一致性hash算法Consistent Hashing 对于原有hash算法hash%n so... 1.话不多说直接上代码,原理或详解自行百度即可 import cn.pheker.utils.Ut ...

  5. 【转】一致性hash算法(consistent hashing)

    consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛: 1  ...

  6. 一致性hash算法 - consistent hashing

    consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛: 1 ...

  7. Nginx的负载均衡 - 一致性哈希 (Consistent Hash)

    Nginx版本:1.9.1 我的博客:http://blog.csdn.net/zhangskd 算法介绍 当后端是缓存服务器时,经常使用一致性哈希算法来进行负载均衡. 使用一致性哈希的好处在于,增减 ...

  8. [转]一致性hash算法 - consistent hashing

    consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛: 1  ...

  9. _00013 一致性哈希算法 Consistent Hashing 新的讨论,并出现相应的解决

    笔者博文:妳那伊抹微笑 博客地址:http://blog.csdn.net/u012185296 个性签名:世界上最遥远的距离不是天涯,也不是海角,而是我站在妳的面前.妳却感觉不到我的存在 技术方向: ...

  10. 一致性哈希算法(c#版)

    最近在研究"一致性HASH算法"(Consistent Hashing),用于解决memcached集群中当服务器出现增减变动时对散列值的影响.后来 在JAVAEYE上的一篇文章中 ...

随机推荐

  1. 用户名_密码获取Access_Token

    http://www.ivanjevremovic.in.rs/live/domination/red/index-async-slider.html http://designova.net/rev ...

  2. CSDN博文大赛火爆开启

    俗话说的好,程序猿会写博,谁也挡不住! 是不是每一个开发人员都能写出好博文,这个非常难说,但能够肯定的是,能写出好博文的,一定是优秀的程序猿! 写作即思考,养成写博文的习惯,既能帮自己整理技术思路,也 ...

  3. barManager.Menu(barSubItem)

    DevExpress 的帮助文档是在太缺乏了,他自己的帮助只有简单描述,没有样例,而它的网站上的在线帮助只有利用它的设计器设计的ToolBar.PopupMenu ,没有利用代码开发的.虽然要利用代码 ...

  4. C# 后台调用script使用类

    在网站的开发的时候,总是会用到一些前台的提示的script的代码,从项目中整理了一份常用的方法. public class Jscript { public Jscript() { // // TOD ...

  5. Js特效总结

    1.//#hidediv2为一个需要隐藏的div  这个功能实现当点击hidediv2以外的其他任何位置时,隐藏该div $(document).click(function() {          ...

  6. 不用css样式表和背景图片实现圆角矩形,超简洁!

    当网站页面的整体布局设计好后,接下来有很多细节的实现是很让人头疼的.其中之一就是圆角矩形的实现. 在网上看了很多圆角矩形的实现方法,基本有两种,一种是用纯css实现,不需要背景图片:另一种是用背景图像 ...

  7. couldn't connect to the device trackpad

  8. js 中的for...in循环

    in:其左边是一个字符串或可以转换成字符串,右边是一个对象或数组 例:var person={firstname:"Bob", lastname:"Kin"}; ...

  9. Unknown system variable 'tx_read_only'

    SpringMVC+SpringDataJPA(1.4.2.RELEASE)+hibernate(4.2.7)+mysql6.0的开发环境,mysql-connector要older than5.1. ...

  10. ctype.h 字符分类与转换

      函数及说明 1 int isalnum(int c)该函数检查传递的字符是否是字母数字. 2 int isalpha(int c)该函数是否传递的字符是字母. 3 int iscntrl(int ...