我正在寻求实现我的 ConsistentHashing,我可以为其提供良好的 HashingFunction。这里解释了使用 SortedMap 的一个不错的实现:https://weblogs.java.net/blog/tomwhite/archive/2007/11/consistency_hash.html
现在就像帖子中建议的那样,我想使用像 MD5 这样具有良好随机性的加密函数。我知道 MD5 会返回固有的 128 位输出,但是我需要随机的 32 位。以下的基数会很高吗?
(1) MD5 输出的前 4 个字节是否足够随机?在这种情况下,我可以只取 128 位 MD5 哈希值中的前 32 位:
class MD5Hashing implements HashFunction{
@Override
public int getHash(String key) throws Exception{
MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] byteArray = digest.digest(key.getBytes("UTF-8"));
ByteBuffer buffer = ByteBuffer.wrap(byteArray);
return buffer.getInt()& 0x7fffffff;
}
}
(2) 如果我只使用 String 的内部 Horner 算法,该算法对 String 中的所有字符使用 31x+y 会怎样?
class StringHashing implements HashFunction{
@Override
public int getHash(String key) throws Exception{
return key.hashCode()& 0x7fffffff;
}
}
(3) 我的内部一致散列(如上面的链接)只是一个 TreeMap 我是否应该使用 BigInteger 来仍然能够从 MD5 或其他加密算法获取所有 128 位?
private final SortedMap<Integer, T> circle = new TreeMap<Integer, T>();
编辑: 看起来两者都不好,我什至尝试从 MD5 哈希值中获取最后 4 个字节。缓冲区.getInt(12)。
运行 5000 个随机字符串后就是分布。 {host4.a.b.com=1599,host3.a.b.com=1075,host2.a.b.com=238,host1.a.b.com=2088}
发现 Murmur hash 具有将字符串输入转换为 32 位哈希输出的 API。也给了我一个非常好的分布。
{host4.a.b.com=1665,host3.a.b.com=1373,host2.a.b.com=648,host1.a.b.com=1314}
http://d3s.mff.cuni.cz/~holub/sw/javamurmurhash/
public static int hash32( final String text) {...}
显然截断某些哈希值并不会降低其安全性,而只是增加冲突,如其他响应中所述:
https://security.stackexchange.com/questions/97377/secure-way-to-shorten-a-hash
对于这个问题,我无法理解
a.b.com
算法到底是如何工作的,也许你可以进一步解释它,分析你得到的不规则分布是否取决于所取的样本(仅5000个输入,或者可能仅是ASCII,或者其他)。