当目标集增长时,循环散列是否可以保持一致?

时间:2013-03-08 03:15:50

标签: php javascript scalability consistent-hashing

循环哈希算法在给定静态目标集的情况下提供一致性。例如:

  1. 我有一组初始目标,我们称之为ABC
  2. 我有一把钥匙,我们称之为x
  3. 我有一个循环哈希函数,我们称之为hash(key, targets)
  4. 当我致电hash(x, [A,B,C])时,x总是哈希到A
  5. 似乎显而易见。我总是得到A x这一事实代表了我在使用循环哈希时所期望的一致性。但是,我们现在考虑如果我添加一个新的会发生什么 节点D

    1. 我的目标集已重新平衡,包括ABCD
    2. 我将我的密钥x重新应用到hash(x, [A,B,C,D])
    3. 由于圈子已重新平衡,因此我无法保证再次获得A
    4. 我错过了什么,或者我只是运气不好?当您开始重新排序节点(例如hash(x, [B,A,D,C]))或者在现有节点列表(例如hash(x, [A,AA,B,C,D]))的中间插入新节点时,问题会进一步加剧。我看了一下圆形散列的学术方面,这种“缩放一致性”似乎并不是它的主要关注点之一。也许我只是使用错误类型的散列算法?

4 个答案:

答案 0 :(得分:1)

您的问题有一个非常简单的解决方案。这是一个如何工作的例子。

让我们假设您有3个真实目标(即物理机器):A,B,C。然后你引入9个虚拟目标:1,2,3,4,5,6,7,8,9并建立静态映射从虚拟目标到真实目标,如下所示:

1, 2, 3 -> A
4, 5, 6 -> B
7, 8, 9 -> C

当您需要读取/写入某个键的值时,首先使用哈希函数将键映射到虚拟目标,然后使用上面显示的静态映射将虚拟目标映射到实际目标。一旦某个真实目标服务于多个虚拟目标,它应该将它们存储在单独的哈希映射中,因此真实目标B有三个单独的哈希映射,用于它所服务的三个虚拟目标。

现在我们要添加新的真实目标:D。我们首先重新平衡我们的静态映射,例如:像这样:

1, 2, 3 -> A
4, 5 -> B
7, 8 -> C
6, 9 -> D

然后,我们将虚拟目标6的哈希地图从真实目标B转移到新的真实目标D。我们还将地图服务虚拟目标9C转移到D。此操作具有复杂性O(n),其中n是传输的值的数量,因为每个真实目标在单独的哈希映射中为每个虚拟目标服务。

要实现良好的负载平衡,虚拟目标的数量应比估计最大可能的实际目标数量多几倍(例如10倍)。

换句话说,该解决方案的主要思想是使用散列函数将键映射到虚拟目标,其中虚拟目标的数量不会改变。然后使用静态映射将虚拟目标映射到真实目标,并且当添加或移除真实目标时,此静态映射会发生变化。

答案 1 :(得分:0)

当您扩展散列函数的允许输出范围时,可以理解某些输入将散列到不同的输出(否则没有扩展范围的点)。唯一的方法是,如果散列函数存储所有先前的结果(或者压缩的,可能有损的形式,如Bloom过滤器),那么它可以记住使用“旧”结果输入它之前见过。

答案 2 :(得分:0)

我无法以一致的方式解释您的整个问题,因此我会猜测您真正想要提出的问题并在此基础上回答。

假设问题:您有一堆对象(例如字符串)并且您拥有一堆计算机,并且您希望将每个对象分配给一台计算机,以便在计算机之间分配工作负载。当机器加入或离开机器池时,您不希望重新调整太多的对象到机器分配(“缩放一致性”)。

我认为你误解了你在哪里散列对象x以映射池[A,B,C]中的机器。我的理解是涉及三个中间步骤。

  1. 计算每个对象的哈希值。假设哈希输出空间像0到2 32 - 1的所有整数一样大。

  2. 为每台机器分配一个值(在相同的数字空间中),它在其生命周期内保持不变。您可能希望随机传播这些数字。

  3. 现在,我们将每个对象分配给最近的向上机器。这意味着如果对象的散列是x,那么它属于机器M,使得M的值是大于x的最小数。

  4. 示例:

    1. 我们有4个字符串对象,它们各自的哈希值在0到999范围内:abc = 314,def = 125,ghi = 802,jkl = 001。

    2. 我们有3台机器,有这些数字:X = 010,Y = 357,Z = 768。

    3. 对象abc = 314属于哪台机器?向上计数,最近的机器是Y = 357 对象ghi = 802属于哪台机器?向上计数,最近的机器是X = 010。

答案 3 :(得分:0)

好的,我想我明白了。

我最终保持哈希算法简单,并使用“校验和”(各种类型)来确保x始终键入同一目标。当添加新目标并且系统重新平衡时,我只是通知所有现有目标有关重新平衡的信息。这样,如果x哈希到目标它不再哈希,那么目标就可以委托给正确的目标。

感谢您的所有回复,如果不是因为您提供的清晰度,我可能没有找到这个解决方案。

干杯,

乔恩