我知道随机UUID在理论上具有非常非常非常低的碰撞概率,但我想知道,在实践中,Java 5的randomUUID()
在没有碰撞方面有多好?有没有人有经验可以分享?
答案 0 :(得分:154)
UUID使用java.security.SecureRandom
,这应该是“密码强”。虽然没有指定实际的实现,并且JVM之间可能有所不同(意味着任何具体的语句仅对一个特定的JVM有效),但它确实要求输出必须通过统计随机数生成器测试。
实现总是可能包含破坏所有这些的微妙错误(请参阅OpenSSH密钥生成错误),但我认为没有任何具体理由担心Java UUID的随机性。
答案 1 :(得分:105)
维基百科有一个非常好的答案 http://en.wikipedia.org/wiki/Universally_unique_identifier#Collisions
需要生成的随机版本4 UUID的数量为至少有一次碰撞的概率为50%,计算如下:
...
这个数字相当于大约85年每秒产生10亿UUID,包含这么多UUID的文件,每个UUID 16字节,大约45艾字节,比现有的最大数据库大很多倍,大概数百PB。
...
因此,为了有十亿分之一的重复机会,必须生成103万亿版本的4个UUID。
答案 2 :(得分:65)
有没有人有经验可以分享?
类型4 UUID有2^122
个可能的值。 (规范说你输入的类型为2位,版本号又输了4位。)
假设您每秒产生100万个随机UUID,那么在您的生命中发生重复的可能性将会非常小。要检测重复,您必须解决每秒比较100万个新UUID与您之前生成的所有UUID 1 的问题!
任何人在现实生活中经历过(即实际上注意到)重复的机会甚至小于消失的......因为寻找碰撞的实际困难。
当然,您通常会使用伪随机数生成器,而不是真正随机数的来源。但我认为我们可以确信,如果您使用可靠的提供商来获取加密强度随机数,那么它将成为加密强度,重复的概率将与理想值相同(无偏差的随机数发生器。
但是,如果您使用带有“损坏”加密随机数生成器的JVM,则所有投注均已关闭。 (这可能包括某些系统中“熵短缺”问题的一些解决方法。或者有人在你的系统或上游修改了你的JRE。)
1 - 假设您使用了匿名评论者提出的“某种二进制btree”,每个UUID将需要O(NlogN)
位RAM内存来表示N
个不同的UUID假设比特的低密度和随机分布。现在乘以1,000,000以及您要运行实验的秒数。我认为测试高质量RNG碰撞所需的时间长度并不实用。甚至没有(假设的)聪明的陈述。
答案 3 :(得分:20)
我不是专家,但我认为多年来有足够聪明的人看着Java的随机数生成器。因此,我还假设随机UUID是好的。因此,对于所有可能的UUID,您应该确实具有理论冲突概率(大约为1:3 × 10^38。是否有人知道这对于随机UUID的变化如何?是上述的1/(16*4)
吗?)
从我的实践经验来看,到目前为止我从未见过任何碰撞。在我得到第一个胡须的那天,我可能已经长出了令人惊讶的长胡须;)
答案 4 :(得分:10)
UUID的原始生成方案是将UUID版本与生成UUID的计算机的MAC地址连接起来,并且自西方采用公历以来,其间隔数为100纳秒。通过表示空间中的单个点(计算机)和时间(间隔的数量),值中发生碰撞的可能性实际上为零。
答案 5 :(得分:7)
在前雇主,我们有一个包含随机uuid的独特专栏。我们在部署后的第一周发生了碰撞。当然,赔率很低但不是零。这就是Log4j 2包含UuidUtil.getTimeBasedUuid的原因。只要您在单个服务器上生成的UUID /毫秒数不超过10,000 UUID,它将生成8,925年唯一的UUID。
答案 6 :(得分:6)
许多答案讨论了为达到50%的碰撞几率而必须生成多少UUID。但是,对于必须(几乎)不可能发生碰撞的应用,50%,25%甚至1%的碰撞几率毫无价值。
程序员经常解雇“不可能”和#34;可以而且确实会发生的其他事件?
当我们将数据写入磁盘或内存并再次读回时,我们理所当然地认为数据是正确的。我们依靠设备的错误纠正来检测任何损坏。但是,未检测到错误的可能性实际上在2 -50 附近。
将类似标准应用于随机UUID是否有意义?如果你这样做,你会发现"不可能"在大约1000亿个随机UUID(2 36.5 )的集合中可能发生冲突。
这是一个天文数字,但是在国家医疗保健系统中逐项计费或在大量设备上记录高频传感器数据等应用肯定会遇到这些限制。如果您正在编写下一个 Hitchhiker的银河指南,不要尝试为每篇文章分配UUID!
答案 7 :(得分:4)
去年我在乐透区比赛,我从未赢过.... 但似乎有彩票有赢家......
doc:http://tools.ietf.org/html/rfc4122
类型1:未实现。如果在同一时刻生成uuid,则可能发生冲突。 impl可以人为地同步,以绕过这个问题。
类型2:永远不会看到实现。
类型3:md5哈希:可能发生冲突(128位-2技术字节)
类型4:随机:可能发生碰撞(作为抽奖)。请注意,jdk6 impl不使用“真正的”安全随机因为开发人员不选择PRNG算法,您可以强制系统使用“差”PRNG算法。所以你的UUID是可预测的。
类型5:sha1哈希:未实现:可能发生冲突(160位-2技术字节)
答案 8 :(得分:3)
我不是专家,但由于每个人都在谈论理论,我想我可以通过一个实际的例子为讨论添加一些内容。在我的数据库中,我使用Java 8 UUID.randomUUID()生成了大约450万个UUID。以下是我发现的一些:
“c0f55f62-b990-47bc-8caa-f42313669948”
“c0f55f62-e81e-4253-8299-00b4322829d5”
“c0f55f62-4979-4e87-8cd9-1c556894e2bb”
“b9ea2498-fb32-40ef-91ef-0ba00060fe64”
“be87a209-2114-45b3-9d5a-86d00060fe64”
“4a8a74a6-e972-4069-B480-bdea1177b21f”
“12fb4958-bee2-4c89-8cf8-edea1177b21f”
如果它真的是随机的,那么拥有这类类似UUID的可能性会相当低,因为我们只考虑了450万个条目。所以,尽管这个功能很好,但就没有碰撞而言,对我来说,似乎 在理论上并不合适。
答案 9 :(得分:1)
我们已经在我们的应用程序中使用Java的随机UUID超过一年,而且非常广泛。但我们从来没有遇到过碰撞。