我正在尝试实现this website上定义的逻辑。其中一个步骤是:
- 将每个服务器字符串哈希到几个(100-200)无符号整数
但我对此感到困惑。有人可以告诉我这意味着什么,以便我可以手动实现逻辑?
// This count is always 2 as per my current setup
int availableservers = Client.getAvailableServers().size();
String key = "MyKey";
int keyid = key.hashCode();
int v = keyid % 1;
String valess = (String) mcc.get(key,v);
答案 0 :(得分:3)
您引用的文章包含指向其SVN代码库的链接:
svn://svn.audioscrobbler.net/misc/ketama/
在这里,它们似乎包含了Java实现:
svn://svn.audioscrobbler.net/misc/ketama/java_ketama/SockIOPool.java
在代码中,您将找到以下内容:
for(long j = 0; j < factor; j++) {
byte[] d = md5.digest((servers[i]+"-"+j).getBytes());
for(int h=0;h<4;h++) {
Long k =
((long)(d[3+h*4]&0xFF) << 24)
| ((long)(d[2+h*4]&0xFF) << 16)
| ((long)(d[1+h*4]&0xFF) << 8)
| ((long)(d[0+h*4]&0xFF));
buckets.put(k, servers[i]);
log.debug( "++++ added " + servers[i] + " to server bucket" );
}
}
此代码为每个服务器创建了总共factor
个哈希值。请注意for循环在散列之前将当前值j
附加到字符串server[i]
。
将此与Frank Pavageau的答案相结合,你很快就会明白发生了什么。
答案 1 :(得分:2)
我猜ketama hash是使用MD5计算的。我找到了示例实现here
public static Long md5HashingAlg(String key) {
MessageDigest md5 = null;
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException( "md5 algorythm found");
}
}
md5.reset();
md5.update(key.getBytes());
byte[] bKey = md5.digest();
long res = ((long)(bKey[3]&0xFF) << 24) | ((long)(bKey[2]&0xFF) << 16) | ((long)(bKey[1]&0xFF) << 8) | (long)(bKey[0]&0xFF);
return res;
}
答案 2 :(得分:1)
Duncan是对的,只需查看来源,看看这个特定的实现是如何运作的。
然而,从概念上讲,无论使用何种哈希算法,如果你需要基于相同键的多个哈希值,你需要做的就是将键连接到几个“常量”,或者至少是已知和可重复的值:
String key = "MyKey";
List<Integer> hashes = new ArrayList<>();
for (String s : Arrays.asList("", "extra1", "extra2")) {
hashes.add((key + s).hashCode());
}
这相当于围绕整数“连续体”分布散列,以重用文章的术语。所以你也可以这样做,就像你实现hashCode()一样:
String key "MyKey";
List<Integer> hashes = new ArrayList<>();
int hash = key.hashCode();
for (int i = 0; i < 100; i++) {
hashes.add(hash);
hash = 31 * hash + 1234567;
}