一致性哈希(Consistent Hashing)
前言:对于一致性哈希已经不是罕见概念,在此只是对原有理论概念的一个整理和用自己的理解讲述,希望对新手有些许帮助,利人利己足矣。
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)的更多相关文章
- 深入一致性哈希(Consistent Hashing)算法原理,并附100行代码实现
转自:https://my.oschina.net/yaohonv/blog/1610096 本文为实现分布式任务调度系统中用到的一些关键技术点分享——Consistent Hashing算法原理和J ...
- 一致性哈希(consistent hashing)算法
文章同步发表在博主的网站朗度云,传输门:http://www.wolfbe.com/detail/201608/341.html 1.背景 我们都知道memcached服务器是不提供分布 ...
- 用于KV集群的一致性哈希Consistent Hashing机制
KV集群的请求分发 假定N为后台服务节点数,当前台携带关键字key发起请求时,我们通常将key进行hash后采用模运算 hash(key)%N 来将请求分发到不同的节点上, 后台节点的增删会引起几乎所 ...
- 一致性hash算法Consistent Hashing
一致性hash算法Consistent Hashing 对于原有hash算法hash%n so... 1.话不多说直接上代码,原理或详解自行百度即可 import cn.pheker.utils.Ut ...
- 【转】一致性hash算法(consistent hashing)
consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛: 1 ...
- 一致性hash算法 - consistent hashing
consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛: 1 ...
- Nginx的负载均衡 - 一致性哈希 (Consistent Hash)
Nginx版本:1.9.1 我的博客:http://blog.csdn.net/zhangskd 算法介绍 当后端是缓存服务器时,经常使用一致性哈希算法来进行负载均衡. 使用一致性哈希的好处在于,增减 ...
- [转]一致性hash算法 - consistent hashing
consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛: 1 ...
- _00013 一致性哈希算法 Consistent Hashing 新的讨论,并出现相应的解决
笔者博文:妳那伊抹微笑 博客地址:http://blog.csdn.net/u012185296 个性签名:世界上最遥远的距离不是天涯,也不是海角,而是我站在妳的面前.妳却感觉不到我的存在 技术方向: ...
- 一致性哈希算法(c#版)
最近在研究"一致性HASH算法"(Consistent Hashing),用于解决memcached集群中当服务器出现增减变动时对散列值的影响.后来 在JAVAEYE上的一篇文章中 ...
随机推荐
- 依赖注入及AOP简述(七)——FQCN请求模式
2.2. FQCN请求模式 为了弥补纯字符串请求模式中的类型安全问题,全类名(FQCN)请求模式就应运而生了.其思想便是,在向容器请求依赖对象的时候,不是通过字符串的标识符.而是通过被请求的依赖 ...
- 关于Windows的139和445端口
上次的月赛中,遇到了一个经典的MS08-067的漏洞,这是一个经典的教科书的漏洞.但是仅限于使用metasploit来攻击这个漏洞.现在我想简单写一些关于139和445端口的东西. 首先提到的是Net ...
- ORACLE数据库存储结构简介(转)
首先,oracle数据库的存储结构可以分为逻辑存储结构和物理存储结构,对于这两种存储结构,oracle是分别进行管理的. 逻辑存储结构:oracle内部的组织和管理数据的方式. 物理存储结构:o ...
- 解决VS2010批量替换时经常由于内存较低而导致VS2010自动关闭的问题
尊重原著作:本文转载自http://www.cnblogs.com/Sharping/p/3165527.html 情况描述 在使用VS2010 开发Web应用程序的时候,批量替换时经常卡死关闭. 一 ...
- java多线程并发例子
public static void main(String[] args) { for(Thread t:getThreads()){ t.start(); } } public static Th ...
- Qt编程学习网站
http://blog.csdn.net/k122769836/article/details/8637677 QT - little_su - 博客频道 - CSDN.NET Qt - 1+1=2 ...
- mysql5 乱码问题解决方案
今天在写项目时碰到了mysql数据库数据乱码的问题,也从网上查了很多方法,前后折腾了两个小时才终于调整好.现在就把调整过程中碰到的一些问题记录下来: 1.项目是SSH架构,一开始我以为是调用hiber ...
- 浏览器加载模式:window.onload和$(document).ready()的区别(详解)
jQuery库文件是在body元素之前加载的,必须等待所有的DOM元素加载后,延迟支持DOM操作,否则就无法获取到. 在延迟等待加载,JavaScript提供了一个事件为load,方法如下: wind ...
- Android 相对布局常用属性
Android 布局属性详解 RelativeLayout用到的一些重要的属性: 第一类:属性值为true或false android:layout_centerHrizontal 水平居中 ...
- 一个可以拓展的垂直多级导航栏 Demo
大四党忙忙碌碌找工作,博客荒废久矣,可谓:终日昏昏醉梦间,忽闻春尽强登山.因过竹院逢僧话,偷得浮生半日闲. 这是个垂直的导航栏,可以有无限多层的子级菜单,看代码注释就够了: <!DOCTYPE ...