一致性Hash算法(转载)
Posted 张小贱1987
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一致性Hash算法(转载)相关的知识,希望对你有一定的参考价值。
原文地址http://blog.csdn.net/caigen1988/article/details/7708806
consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛;
2 由于访问加重,需要添加 cache ,这时候 cache 是 N+1 台,映射公式变成了 hash(object)%(N+1) ;
1 和 2 意味着什么?这意味着突然之间几乎所有的 cache 都失效了。对于服务器而言,这是一场灾难,洪水般的访问都会直接冲向后台服务器;
再来考虑第三个问题,由于硬件能力越来越强,你可能想让后面添加的节点多做点活,显然上面的 hash 算法也做不到。
有什么方法可以改变这个状况呢,这就是 consistent hashing...
Hash 算法的一个衡量指标是单调性( Monotonicity ),定义如下:
单调性是指如果已经有一些内容通过哈希分派到了相应的缓冲中,又有新的缓冲加入到系统中。哈希的结果应能够保证原有已分配的内容可以被映射到新的缓冲中去,而不会被映射到旧的缓冲集合中的其他缓冲区。
容易看到,上面的简单 hash 算法 hash(object)%N 难以满足单调性要求。
consistent hashing 是一种 hash 算法,简单的说,在移除 / 添加一个 cache 时,它能够尽可能小的改变已存在 key 映射关系,尽可能的满足单调性的要求。
下面就来按照 5 个步骤简单讲讲 consistent hashing 算法的基本原理。
接下来考虑 4 个对象 object1~object4 ,通过 hash 函数计算出的 hash 值 key 在环上的分布如图 2 所示。
Consistent hashing 的基本思想就是将对象和 cache 都映射到同一个 hash 数值空间中,并且使用相同的hash 算法。
假设当前有 A,B 和 C 共 3 台 cache ,那么其映射结果将如图 3 所示,他们在 hash 空间中,以对应的 hash值排列。
说到这里,顺便提一下 cache 的 hash 计算,一般的方法可以使用 cache 机器的 IP 地址或者机器名作为hash 输入。
现在 cache 和对象都已经通过同一个 hash 算法映射到 hash 数值空间中了,接下来要考虑的就是如何将对象映射到 cache 上面了。
因此这里仅需要变动对象 object4 ,将其重新映射到 cache C 上即可;参见图 4 。
因此这里仅需要变动对象 object2 ,将其重新映射到 cache D 上;参见图 5 。
考量 Hash 算法的另一个指标是平衡性 (Balance) ,定义如下:
平衡性是指哈希的结果能够尽可能分布到所有的缓冲中去,这样可以使得所有的缓冲空间都得到利用。
为了解决这种情况, consistent hashing 引入了"虚拟节点"的概念,它可以如下定义:
objec1->cache A2 ; objec2->cache A1 ; objec3->cache C1 ; objec4->cache C2 ;
因此对象 object1 和 object2 都被映射到了 cache A 上,而 object3 和 object4 映射到了 cache C 上;平衡性有了很大提高。
引入"虚拟节点"后,映射关系就从 { 对象 -> 节点 } 转换到了 { 对象 -> 虚拟节点 } 。查询物体所在 cache时的映射关系如图 7 所示。
"虚拟节点"的 hash 计算可以采用对应节点的 IP 地址加数字后缀的方式。例如假设 cache A 的 IP 地址为202.168.14.241 。
引入"虚拟节点"前,计算 cache A 的 hash 值:
引入"虚拟节点"后,计算"虚拟节"点 cache A1 和 cache A2 的 hash 值:
Hash("202.168.14.241#1"); // cache A1
Hash("202.168.14.241#2"); // cache A2
这就要由hash算法来保证了,均匀分布是概率上的均匀,当虚拟节点足够时,就能保证大概均匀了。
2.假如cache通过hash函数计算出的值和 object通过hash函数计算出来的值是同一个hash值怎么办?
那object应该指向哪个cache?
C++实现方法:转自:http://www.cnblogs.com/coser/archive/2011/11/27/2265134.html
一致性hash算法实现有两个关键问题需要解决,一个是用于结点存储和查找的数据结构的选择,另一个是结点hash算法的选择。
笔者用C++语言对一致性hash算法进行了实现,下面我将会描述下一些关键细节。
1、首先定义实体结点类、虚拟结点类。一个实体结点对应多个虚拟结点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | /*实体结点*/ class CNode_s { public: /*构造函数*/ CNode_s(); CNode_s(char * pIden , int pVNodeCount , void * pData);
/*获取结点标示*/ const char * getIden();
/*获取实体结点的虚拟结点数量*/ int getVNodeCount();
/*设置实体结点数据值*/ void setData(void * data);
/*获取实体结点数据值*/ void * getData(); private: void setCNode_s(char * pIden, int pVNodeCount , void * pData); char iden[100];/*结点标示串*/ int vNodeCount;/*虚拟结点数目*/ void * data;/*数据结点*/ }; |
虚拟结点 CVirtualNode_s:虚拟结点有一指针指向实体结点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | /*虚拟结点*/ class CVirtualNode_s { public: /*构造函数*/ CVirtualNode_s(); CVirtualNode_s(CNode_s * pNode);
/*设置虚拟结点所指向的实 以上是关于一致性Hash算法(转载)的主要内容,如果未能解决你的问题,请参考以下文章 |