(我正在使用' guid'作为一系列随机字母/数字的术语。)
我正在使用一个函数来创建一个唯一的GUID。功能是:
function guid() {
return sprintf('%04X%04X-%04X-%04X-%04X-%04X%04X%04X',
mt_rand(0, 65535), mt_rand(0, 65535),
mt_rand(0, 65535), mt_rand(16384, 20479),
mt_rand(32768, 49151), mt_rand(0, 65535),
mt_rand(0, 65535), mt_rand(0, 65535));
}
返回类似A881264F-AB87-4592-BFC1-714AFFDEE698'的值。该功能用于为上传的图片分配(希望)唯一的文件名。 (实际的图像文件名与表中的行中的GUID值一起存储。)意图是每个图片的文件名都是唯一的。
这项应用已经有好几年了。最近我已经得到了我认为是重复文件名的内容,因此记录不会指向原始图片文件名,而是随机获取(重新使用)现有文件名的新图片。
我知道我可能需要在文件名中添加其他字符,例如日期/时间戳,以便我可以确保文件名是(并且始终是唯一的)。
我的问题与“机会”有关。在很长一段时间内产生了重复的GUID。
假设GUID是作为上述函数创建的,结果类似于' A881264F-AB87-4592-BFC1-714AFFDEE698',该函数可能有什么机会(可能不是正确的术语)拿出相同的结果?
请注意,这不是关于多少'会有不同的结果,但该函数返回相同结果的几率是多少?
答案 0 :(得分:0)
基本的经验法则是birthday problem。它表示,在人群中,如果人群中存在sqrt(N)元素,则存在约50%的碰撞概率,其中N是可能的值(它是近似值)。
此GUID具有122位状态。因此,在生成2 ^ 61个元素后,您将获得约50%概率的碰撞。
查看链接的维基百科页面,在生成~10 ^ 10个元素后会产生一个碰撞,其概率为~10 ^ -17(这是我的近似值,使用近似公式,但数量级是这里很重要。)
也许您想停止使用GUID,并使用更紧凑的编码随机状态的方式,因此在相同长度的文件名中,您可以放置更多状态,从而降低碰撞的可能性。
答案 1 :(得分:0)
geza的答案在技术上是正确的,但我认为它得出了错误的结论并错过了mt_rand
的背景。具有122位状态的GUID足够随机,在执行像命名图片这样简单的操作时,您可以预期永远不会遇到冲突。在这种情况下,世界上没有足够的图片来考虑碰撞。 2 ^ 61是一个非常高的数字。因此,我不建议您不要试图获得更长的状态。
现在,mt_rand
的背景很重要:
如果您使用mt_srand
以非正确的随机方式设置种子,则可能会遇到重复。
如果用户不应该猜测随机标识符,则根本不应使用mt_rand
。即使它有很长一段时间,但它很容易预测。 (例如:http://www.openwall.com/lists/john-users/2012/09/20/2)如果用户可以完全影响名称,可以故意进行冲突。