【发布时间】:2016-03-06 06:21:55
【问题描述】:
我正在使用 PHP 的 crc32 函数为 MongoId 生成等效的数字,因为我在 mysql 搜索中使用此数字 id,因为字符串搜索很慢。
我遇到了一个案例,其中 crc32 为两个不同的 mongoid 提供了相同的数值。
任何帮助或建议将不胜感激。
谢谢 高拉夫
【问题讨论】:
我正在使用 PHP 的 crc32 函数为 MongoId 生成等效的数字,因为我在 mysql 搜索中使用此数字 id,因为字符串搜索很慢。
我遇到了一个案例,其中 crc32 为两个不同的 mongoid 提供了相同的数值。
任何帮助或建议将不胜感激。
谢谢 高拉夫
【问题讨论】:
@MarkAdler 的回答解释了为什么您会遇到哈希冲突。但如果我站在你的立场上,我会对我能做些什么更感兴趣。
当然,您可以做的是使用不同的散列算法来产生更长的散列(发生冲突的可能性更小),但速度仍然可以接受。您会在programmers.stackexchange.com 的this question 中找到对几个备选方案的高度评价。它们都有冲突(巧合的是,CRC32 在那个答案的测试集中表现得很好),但你可以在 mongoids 上尝试其中的一些,看看会发生什么。
我还发现了this clever suggestion:要生成 64 位散列,您可以采用两种不同的 32 位散列算法并将散列连接起来(当然这或多或少会减半速度您的哈希值)。
更健壮的解决方案是在编写代码时理解散列是一个桶,有时您会从 crc32 查询中得到多个结果(或错误的结果)。只需添加第二步来检查返回记录的未散列 ID。由于只有少数几首热门歌曲,因此不会花很长时间。
【讨论】:
除非您的字符串为 4 个字节或更少,否则许多字符串将具有任何给定的 CRC-32 值是不可避免的。如果您甚至只有一个超过 2^32 个可能的字符串,那么绝对可以保证这些字符串中至少有两个将映射到相同的 CRC-32。
没有任何帮助或建议。你不能期望没有冲突,除非可能的字符串比可能的 CRC 少。
顺便说一句,你可以用我的spoof code 有意地构造这样的情况,它可以让你给它一组你允许在字符串中更改的位,它会告诉你哪些位可以翻转为了获得所需的 CRC。
【讨论】: