在JavaScript中生成UUID时的冲突?

这涉及到这个问题 。 我正在使用这个答案在JavaScript中生成UUID:

'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8); return v.toString(16); }); 

这个解决scheme似乎工作正常,但是我碰到了碰撞。 这是我有:

  • 在Google Chrome中运行的networking应用
  • 16个用户。
  • 这些用户在过去2个月内已经生成了约4000个UUID。
  • 我得到了大约20个碰撞 – 例如今天新的UUID与大约2个月前(不同的用户)相同。

所以问题是:

  1. 什么导致这个问题?
  2. 我怎样才能避免它?

我最好的猜测是Math.random()因为某种原因在你的系统上被破坏了(这听起来很古怪)。这是我见过的第一个碰到碰撞的报告。

node-uuid有一个testing工具 ,可以用来testing代码中hex数字的分布。 如果这看起来不错,那么它不是Math.random(),所以然后尝试用你使用的UUID实现代替到那里的uuid()方法,看看你是否仍然得到好的结果。

[更新:在启动时刚刚看到Veselin关于Math.random()的错误报告。 由于问题只在启动时进行,因此node-uuidtesting不太可能有用。 我将在devoluk.com链接上进行更详细的评论。]

确实有碰撞,但只有在谷歌浏览器。 看看我在这里的话题的经验

http://devoluk.com/google-chrome-math-random-issue.html

似乎碰撞只发生在Math.random的前几个调用。 因为如果你只是运行上面的createGUID / testGUIDs方法(这显然是我第一次尝试),它只是没有任何冲突的工作。

因此,要进行全面testing,需要重新启动Google Chrome,生成32字节,重新启动Chrome,生成,重新启动,生成…

只是为了让其他人可以意识到这一点 – 我使用这里提到的UUID生成技术遇到了惊人的大量明显的碰撞。 即使我切换到随机数发生器的seedrandom后,这些冲突仍然继续。 就像你想象的那样,我把头发撕掉了。

我终于发现问题几乎与Google的networking爬虫机器人完全相关。 只要我开始忽略用户代理字段中的“googlebot”的请求,冲突消失。 我猜测他们必须以一种半智能的方式cachingJS脚本的结果,最终的结果是他们的蜘蛛浏览器不能算作普通浏览器的行为方式。

只是一个供参考。

我想张贴这个作为您的问题的评论,但显然StackOverflow不会让我。

我使用您发布的UUIDalgorithm,在Chrome中进行了10万次迭代的基本testing,没有发现冲突。 这是一个代码片段:

 var createGUID = function() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8); return v.toString(16); }); } var testGUIDs = function(upperlimit) { alert('Doing collision test on ' + upperlimit + ' GUID creations.'); var i=0, guids=[]; while (i++<upperlimit) { var guid=createGUID(); if (guids.indexOf(guid)!=-1) { alert('Collision with ' + guid + ' after ' + i + ' iterations'); } guids.push(guid); } alert(guids.length + ' iterations completed.'); } testGUIDs(100000); 

你确定这里没有别的东西吗?