这基本上是一个数学问题,但编程相关:如果我有10亿个包含URL的字符串,并且我采用每个字符串的MD5哈希的前64位,我应该期望什么样的冲突频率? / p>
如果我只有1亿个网址,答案会如何变化?
在我看来,碰撞将非常罕见,但这些事情往往令人困惑。
使用MD5以外的其他东西会更好吗?请注意,我不是在寻找安全性,只是一个很好的快速哈希函数。此外,MySQL中的本机支持很不错。
答案 0 :(得分:6)
如果MD5的前64位构成了具有理想分布的散列,那么生日悖论仍然意味着你会得到每2 ^ 32个URL的冲突。换句话说,碰撞的概率是URL的数量除以4,294,967,296。有关详细信息,请参阅http://en.wikipedia.org/wiki/Birthday_paradox#Cast_as_a_collision_problem。
在MD5中丢掉一半的比特我感觉不舒服;最好将高位和低位64位字进行异或,以便给它们混合的机会。再说一次,MD5绝不是快速或安全的,所以我根本不打扰它。如果你想要炫目的速度和良好的分布,但没有安全的假装,你可以尝试64位版本的MurmurHash。有关详细信息和代码,请参阅http://en.wikipedia.org/wiki/MurmurHash。
答案 1 :(得分:2)
您已将此标记为“birthday-paradox”,我认为您know the answer already。
P(Collision) = 1 - (2^64)!/((2^64)^n (1 - n)!)
在你的情况下,n是10亿。
使用MD5之外的其他内容会更好一点,因为MD5有pratical collusion problem。
答案 2 :(得分:2)
从我看到的,你需要一个具有以下要求的哈希函数,
此hash function survey可用于深入了解最适合您的功能 我建议从这里尝试多个函数,并为可能的输入集定义它们(选择几十亿个你认为会看到的URL)。
您实际上可以为测试URL列表生成another column like this test survey,以表征和选择您可能要检查的现有或任何新哈希函数(该表中的更多行)。他们有MSVC ++源代码(reference to ZIP link)。
更改散列函数以适合您的输出宽度(64位)将为您的应用程序提供更准确的表征。
答案 3 :(得分:2)
如果你有2 ^ n个哈希可能性,当你有2 ^(n / 2)项时,有超过50%的碰撞几率。
E.G。如果你的散列是64位,你有2 ^ 64个散列可能性,如果你在一个集合中有2 ^ 32个项目,你有50%的碰撞几率。
答案 4 :(得分:1)
只需使用哈希,就总有可能发生冲突。并且您事先不知道在您的网址列表中会发生一次或两次,甚至数百或数千次碰撞。
概率仍然只是一个概率。就像扔骰子10或100次一样,获得所有六个人的几率是多少?概率表明它很低,但它仍然可能发生。甚至可能连续多次......
因此,虽然birthday paradox向您展示了如何计算概率,但仍需要确定是否可以接受碰撞。
......碰撞是可以接受的,而且哈希仍然是正确的方法;找到64位散列算法而不是依赖具有良好分布的“half-a-MD5”。 (虽然它可能有...)