consistent hashing(一致性hash)

consistent hashing(一致性hash)

1997年,一致性hash首次出现在STOC年会上,但是在那时候该算法被称”it had no hope of being practical”,时过境迁,如今一致性hash在分布式缓存里非常重要

一致性hash算法提出了在动态变化的Cache环境中,判定哈希算法好坏的四个定义:

1、平衡性(Balance):平衡性是指哈希的结果尽可能分布到所有的缓冲中去,使缓冲空间得到充分利用。

2、单调性(Monotonicity):单调性是指如果已经有一些内容通过哈希分派到了相应的缓冲中,又有新的缓冲加入到系统中。哈希的结果应能够保证原有已分配的内容可以被映射到原有的或者新的缓冲中去,而不会被映射到旧的缓冲集合中的其他缓冲区。

3、分散性(Spread):在分布式环境中,终端有可能只看到其中的一部分缓冲。当终端希望通过哈希过程将内容映射到缓冲上时,由于不同终端所见的缓冲范围有可能不同,从而导致哈希的结果不一致,最终的结果是相同的内容被不同的终端映射到不同的缓冲区中。这种情况导致相同内容被存储到不同缓冲中去,降低了系统存储的效率。分散性的定义就是上述情况发生的严重程度。好的哈希算法应能够尽量避免不一致的情况发生,也就是尽量降低分散性。

4、负载(Load):对于一个特定的缓冲区而言,可能被不同的用户映射为不同的内容。与分散性一样,这种情况也是应当避免的,因此好的哈希算法应能够尽量降低缓冲的负荷。

核心思想:将数据对象(x)做hash,同时,对缓存服务器(s)做hash,他们将被哈希到同一个圆环,大小是32位的值

为了明白哪一个数据对象分配到哪一个缓存服务器上,图1所示

数据对象保存在顺时针上(clockwise)最近的缓存服务器上,n个缓存服务器将圆环分为n个段,也就是说,一个缓存服务器将负责一段区域的数据对象

这种简单的想法带来了一些好处:

(1), 假设在一个好的hash函数下,对称的,n个cache server在理想情况下,每个服务器将cache 1/n 个数据对象(这是难以实现的,不过下面我们可以通过replication来改善)

(2), 这点非常有意义,假设我们新增加一个cache server,思考一下,哪些数据对象将被移动?

结合这两个特点,意味着,在理想情况下,加入第n个cache server只会重定向 1/n 的数据对象,如果希望均匀的分布负载,则这是最好的情况–显然,对于新加入的缓存服务器,它里面的数据对象必须从旧的服务器上移动过来。相反,如果用普通的hash方案,比如传统的余数法,平均情况下,只有 1/n 的数据对象不需要重定向,这非常难受。

我们如何实现标准的哈希表操作如Lookup与Insert?对于给定的一个数据对象x,这两个操作都归结为顺时针高效的扫描出:

最小的h(s),使得满足 h(s) ≥ h(x)

因此,我们需要一个数据结构,该数据结构用来storing cache names,和与之对应的哈希值作为key,而且支持快速的Successor操作(就是寻找后继的函数)。

很明显,有过学习数据结构知识的同学可能已经想到二叉搜索树了,该数据结构隐含了所存储的数据集的一个大小顺序,而且容易得到一个Successor function。这里推荐红黑树,查找一个cache及对应的数据对象所消耗时间是 O(logn),n是红黑树节点数量。

根据上面的图解分析,一致性哈希算法满足了单调性以及一般hash算法的分散性。

一致性hash的平衡性

为了接近(1)中的所谓理想情况,即数据均匀分布在每台缓存服务器上,有一种方法:

对每个缓存服务器s,制造k个”virtual copies”,每个虚拟节点通过不同的名字(比如同一个ip+不同序号)得到 h1(s),…,hk(s)。

举一个例子,如图3:

有编号分别为{0, 1, 2}3个server,若k = 4,我们将会有12个server在圆环上,4个0,4个1,4个2,这样的复制(replication),将会增加平衡二叉树上的节点,但会改善因圆环上的数据对象分布不均而导致的负载不平衡的问题。通常,选择 k ≈ log2n 足以得到合理的负载平衡,原因可自行google

原文可见
http://theory.stanford.edu/~tim/s17/l/l1.pdf

http://blog.huanghao.me/?p=14

你可能感兴趣的:(hash)