网上有很多关于一致性散列的信息,以及可用的多种语言的实现。该主题的维基百科条目引用了具有相同目标的另一种算法:
此算法看起来更简单,并且不需要在环周围添加副本/虚拟来处理不均匀的加载问题。正如文章所提到的,它似乎在O(n)中运行,这对于大n来说是一个问题,但引用一篇文章说明它可以被构造为在O(log n)中运行。
对于在这方面有经验的人,我的问题是,为什么人们会选择一致的哈希而不是HRW,反之亦然?是否存在其中一种解决方案是更好的选择的用例?
非常感谢。
答案 0 :(得分:16)
主要是我会说一致哈希的优势在于热点。根据实现,可以手动修改令牌范围以处理它们。
如果以某种方式你最终得到热点(即由糟糕的哈希算法选择引起),那么除了删除热点并添加一个应该平衡请求的新热点之外,你无能为力。
HRW的一大优势是,当您添加或删除节点时,您可以在所有节点之间保持均匀分布。通过一致的哈希,他们通过为每个节点提供200个左右的虚拟节点来解决这个问题,这也使得手动管理范围变得困难。
答案 1 :(得分:8)
作为一个只需要在这两种方法之间做出选择并最终为HRW哈希进行选择的人:我的用例是一个简单的负载平衡,完全没有重新分配要求 - 如果一个节点死了,那么完全可以选择一个新的,重新开始。不需要对现有数据进行重新平衡。
1)Consistent Hashing需要节点和vnode的持久性hashmap(或者至少是一个敏感的实现,你可以在每个请求上构建所有对象....但你真的不喜欢'我想!)。 HWR没有(它是无状态的)。当机器加入或离开集群时,不需要修改任何内容 - 不需要担心并发性(除了您的客户端能够很好地查看集群状态,这两种情况都是相同的)
2)HRW更容易解释和理解(代码更短)。例如,这是在Riverbed Stingray TrafficScript中实现的完整HRW算法。 (注意,有更好的哈希算法可供选择而不是MD5 - 这对于这项工作来说太过分了)
$nodes = pool.listActiveNodes("stingray_test");
# Get the key
$key = http.getFormParam("param");
$biggest_hash = "";
$node_selected = "";
foreach ($node in $nodes) {
$hash_comparator = string.hashMD5($node . '-' . $key);
# If the combined hash is the biggest we've seen, we have a candidate
if ( $hash_comparator > $biggest_hash ) {
$biggest_hash = $hash_comparator;
$node_selected = $node;
}
}
connection.setPersistenceNode( $node_selected );
3)当您丢失或获得节点时,HRW会提供均匀分布(假设您选择了合理的散列函数)。 Consistent Hashing不能保证,但是有足够的vnode可能不会成为问题
4)一致路由可能更快 - 在正常操作中它应该是一个命令Log(N),其中N是节点数* vnodes的复制因子。但是,如果你没有很多节点(我没有),那么HRW对你来说可能足够快。
4.1)正如你所提到的,维基百科提到有一种方法可以在log(N)时间内完成HWR。我不知道怎么做!我对5节点上的O(N)时间感到满意.....
最后,HRW的简单性和无国籍性为我做出了选择....