Php 随着目标集的增长,循环散列能否保持一致?

Php 随着目标集的增长,循环散列能否保持一致?,php,javascript,scalability,consistent-hashing,Php,Javascript,Scalability,Consistent Hashing,循环哈希算法在给定一组静态目标时提供一致性。例如: 我有一组初始目标,让我们称它们为A,B和C 我有一把钥匙,我们叫它x 我有一个循环散列函数,我们称之为hash(key,targets) 当我调用hash(x[A,B,C])时,x总是哈希到A 看起来很明显。我总是得到给定的x的A这一事实代表了我在使用循环哈希时所期望的一致性。但是,现在让我们考虑一下,如果我添加了一个新的 节点D: 我的目标集重新平衡,包括A、B、C和D 我将我的密钥x重新应用到hash(x[A,B,C,D]) 因为圆是重新平

循环哈希算法在给定一组静态目标时提供一致性。例如:

  • 我有一组初始目标,让我们称它们为
    A
    B
    C
  • 我有一把钥匙,我们叫它
    x
  • 我有一个循环散列函数,我们称之为
    hash(key,targets)
  • 当我调用
    hash(x[A,B,C])
    时,
    x
    总是哈希到
    A
  • 看起来很明显。我总是得到给定的
    x
    A
    这一事实代表了我在使用循环哈希时所期望的一致性。但是,现在让我们考虑一下,如果我添加了一个新的 节点
    D

  • 我的目标集重新平衡,包括
    A
    B
    C
    D
  • 我将我的密钥
    x
    重新应用到
    hash(x[A,B,C,D])

  • 因为圆是重新平衡的,我不能保证再得到
    A

  • 我是错过了什么还是只是运气不好?当您开始重新排序节点(例如<代码>散列(x,[b,a,d,c])< />),或者如果在现有节点列表中间插入新节点(例如,<代码> hash(x,[a,a],b,c,d])/代码>时,问题进一步加剧。我已经研究了循环哈希的学术方面,这种类型的“缩放一致性”似乎不是它主要关注的问题之一。也许我只是使用了错误类型的散列算法?

    当您扩展散列函数的允许输出范围时,一些输入将散列到不同的输出(否则扩展范围就没有意义了)。否则的唯一方法是,如果哈希函数存储所有以前的结果(或压缩的、可能有损的结果,如Bloom过滤器),这样它就可以记住对以前看到的输入使用“旧”结果。

    我无法以一致的方式解释您的整个问题,因此,我将根据这一点猜出你真正想问和回答什么

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

    我认为您有一个误解,您说您散列对象
    x
    以映射池中的机器
    [a,B,C]
    。我的理解是,有三个中间步骤

  • 计算每个对象的哈希值。假设散列输出空间与0到232之间的所有整数一样大− 一,

  • 为每台机器分配一个值(在相同的数字空间中),该值在其生命周期内保持不变。你会想把这些数字随机地分散开来

  • 现在,我们指定每个对象属于最近的向上机器。这意味着如果对象的散列是x,那么它属于机器M,因此M的值是大于x的最小数字

  • 例如:

  • 我们有4个字符串对象,它们各自的哈希值在0到999之间:abc=314,def=125,ghi=802,jkl=001

  • 我们有三台机器,它们的编号是:X=010,Y=357,Z=768

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


  • 你的问题有一个很简单的解决办法。下面是一个如何工作的示例

    假设您有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
    
    1, 2, 3 -> A
    4, 5 -> B
    7, 8 -> C
    6, 9 -> D
    
    当需要读/写某个键的值时,首先使用哈希函数将该键映射到虚拟目标,然后使用上面所示的静态映射将虚拟目标映射到真实目标。一旦某个真实目标服务于多个虚拟目标,它应该将它们存储在单独的散列映射中,因此真实目标B为其服务的三个虚拟目标具有三个单独的散列映射

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

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

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

    换句话说,解决方案的主要思想是使用哈希函数将密钥映射到虚拟目标,其中虚拟目标的数量不变。然后,静态映射用于将虚拟目标映射到真实目标,当添加或删除真实目标时,静态映射会发生变化。

    好的,我想我知道了

    我最终保持了散列算法的简单性,并使用“校验和”(排序)来确保x始终指向同一目标。当添加了一个新的目标,并且系统重新平衡时,我只需将重新平衡的情况通知所有现有的目标。这样,如果x散列到一个不应该再散列到的目标,那么该目标就可以委托给正确的目标

    谢谢你们的回复,如果不是因为你们提供的清晰,我可能不会想到这个解决方案

    干杯


    Jon

    对不起,我找不到太多关于循环哈希的资料。你的意思是一致的哈希和DHT吗?你的回答恰当地解释了我所理解的“循环哈希”