我正在研究在我正在编写的一些 java 代码中使用一致的哈希算法。guava Hashing 库有一个consistentHash(HashCode, int)
方法,但文档相当缺乏。我最初的希望是,我可以只使用consistentHash()
简单的会话亲和性来在一组后端服务器之间有效地分配负载。
有没有人有一个如何使用这种方法的真实例子?特别是我关心管理从目标范围中移除存储桶。
例如:
@Test
public void testConsistentHash() {
List<String> servers = Lists.newArrayList("server1", "server2", "server3", "server4", "server5");
int bucket = Hashing.consistentHash(Hashing.md5().hashString("someId"), servers.size());
System.out.println("First time routed to: " + servers.get(bucket));
// one of the back end servers is removed from the (middle of the) pool
servers.remove(1);
bucket = Hashing.consistentHash(Hashing.md5().hashString("blah"), servers.size());
System.out.println("Second time routed to: " + servers.get(bucket));
}
导致输出:
第一次路由到:server4 第二次路由到:server5
我想要的是在删除列表中较早的服务器后将该标识符(“someId”)映射到同一台服务器。所以在上面的示例中,删除后我想我希望存储桶 0 映射到“server1”,存储桶 1 映射到“server3”,存储桶 2 映射到“server4”,存储桶 3 映射到“server5”。
我是否应该维护一个单独的(比列表更复杂的)数据结构来管理存储桶的删除和添加?我想我可能已经设想了一个更复杂的哈希 API,它可以在为我添加和删除特定存储桶之后管理重新映射。
注意:我知道示例代码使用了一个小的输入和存储桶集。我在 100 个存储桶中尝试了 1000 次输入,结果是一样的。当我将 更改为 99 时,映射到存储桶 0-98 的输入保持不变,buckets
并且存储桶 99 分布在剩余的 99 个存储桶中。