Hash 使用一个64位数字唯一标识URL

Hash 使用一个64位数字唯一标识URL,hash,hash-collision,birthday-paradox,Hash,Hash Collision,Birthday Paradox,这基本上是一个数学问题,但与编程非常相关:如果我有10亿个包含URL的字符串,并且我取每个字符串的MD5哈希的前64位,我应该期望什么样的冲突频率 如果我只有1亿个URL,答案会如何变化 在我看来,碰撞将是极其罕见的,但这些事情往往令人困惑 使用MD5以外的东西会更好吗?请注意,我不是在寻找安全性,只是一个好的快速散列函数。另外,MySQL中的本机支持也不错 编辑:我想你已经把这个标记为生日悖论了 在你的例子中,n是10亿 使用MD5之外的其他东西会更好一些,因为MD5有。如果MD5的前64位构

这基本上是一个数学问题,但与编程非常相关:如果我有10亿个包含URL的字符串,并且我取每个字符串的MD5哈希的前64位,我应该期望什么样的冲突频率

如果我只有1亿个URL,答案会如何变化

在我看来,碰撞将是极其罕见的,但这些事情往往令人困惑

使用MD5以外的东西会更好吗?请注意,我不是在寻找安全性,只是一个好的快速散列函数。另外,MySQL中的本机支持也不错


编辑:

我想你已经把这个标记为生日悖论了

在你的例子中,n是10亿


使用MD5之外的其他东西会更好一些,因为MD5有。

如果MD5的前64位构成了具有理想分布的散列,生日悖论仍然意味着每2^32个URL都会发生冲突。换句话说,冲突的概率是URL的数量除以4294967296。有关详细信息,请参阅


在MD5中扔掉一半,我会感到不舒服;最好对高64位和低64位字进行异或运算,使它们有机会混合。再说一次,MD5决不是快速或安全的,所以我一点也不担心它。如果您希望获得良好的分发速度,但又不想假装安全,那么可以尝试64位版本的BurruHash。有关详细信息和代码,请参见。

据我所知,您需要一个具有以下要求的哈希函数

将任意长度的字符串哈希为64位值 小心-避免碰撞 不一定需要单向安全性 最好是快速-这是非安全应用程序的必要特征 这可能有助于深入了解最适合您的功能。 我建议您在这里尝试多个函数,并为您可能的输入集描述它们,选择您认为会看到的数十亿个URL

实际上,您可以为您的测试URL列表生成特征,并从现有或任何新的哈希函数中选择该表中可能需要检查的更多行。他们从MSVC++源代码开始


更改哈希函数以适合您的输出宽度64位,将为您的应用程序提供更准确的特性描述。

仅使用哈希函数,始终存在冲突的可能性。而且你事先不知道在你的URL列表中是否会发生一次或两次,甚至数百次或数千次冲突

概率仍然只是一个概率。这就像掷骰子10或100次,得到全部6的几率有多大?虽然概率很低,但仍然有可能发生。甚至可能连续很多次

因此,虽然演示了如何计算概率,但仍然需要确定碰撞是否可以接受


…冲突是可以接受的,哈希仍然是正确的选择;找到一个64位哈希算法,而不是依赖具有良好分布的半个MD5。虽然如果有2^n散列可能性,它可能有…

,但当有2^n/2个项目时,冲突的可能性超过50%


例如,如果您的散列为64位,则有2^64个散列可能性,如果集合中有2^32个项目,则有50%的冲突几率。

那么,呃,您的意思是上面提到的2^64 18446744073709551616吗?这个问题讲的是64位,而不是32位。不,他指的是2^32。这意味着对于100万个URL,发生1次冲突的可能性不到1%。我想我要了。没错,伊萨多克,我的意思是2^32,不是2^64。这就是生日悖论的全部要点:任何两个随机值相互匹配的几率都比任何一个随机值匹配单个目标的几率高出很多
P(Collision) = 1 - (2^64)!/((2^64)^n (1 - n)!)