我知道随机uuid在理论上有非常非常非常低的碰撞概率,但我想知道,在实践中,Java的randomUUID()在没有碰撞方面有多好?有人有经验可以分享吗?


当前回答

在以前的雇主那里,我们有一个包含随机uuid的唯一列。在部署后的第一周就发生了碰撞。当然,几率很低,但也不是零。这就是为什么Log4j 2包含UuidUtil.getTimeBasedUuid。只要在一台服务器上每毫秒生成的UUID不超过10,000个,它就会生成一个在8,925年内惟一的UUID。

其他回答

维基百科给出了一个很好的答案 http://en.wikipedia.org/wiki/Universally_unique_identifier#Collisions

the number of random version 4 UUIDs which need to be generated in order to have a 50% probability of at least one collision is 2.71 quintillion, computed as follows: ... This number is equivalent to generating 1 billion UUIDs per second for about 85 years, and a file containing this many UUIDs, at 16 bytes per UUID, would be about 45 exabytes, many times larger than the largest databases currently in existence, which are on the order of hundreds of petabytes. ... Thus, for there to be a one in a billion chance of duplication, 103 trillion version 4 UUIDs must be generated.

在以前的雇主那里,我们有一个包含随机uuid的唯一列。在部署后的第一周就发生了碰撞。当然,几率很低,但也不是零。这就是为什么Log4j 2包含UuidUtil.getTimeBasedUuid。只要在一台服务器上每毫秒生成的UUID不超过10,000个,它就会生成一个在8,925年内惟一的UUID。

UUID使用java.security。SecureRandom,它被认为是“加密强的”。虽然没有指定实际的实现,并且在不同的JVM之间可能有所不同(这意味着所做的任何具体语句只对一个特定的JVM有效),但它确实要求输出必须通过统计随机数生成器测试。

实现中总是可能包含破坏这一切的细微错误(参见OpenSSH密钥生成错误),但我不认为有任何具体理由担心Java uuid的随机性。

我去年买彩票,但我从来没有中过.... 但似乎彩票中了奖…

Doc: https://www.rfc-editor.org/rfc/rfc4122

类型1:未实现。如果uuid在同一时刻生成,则可能发生冲突。Impl可以人为地实现a同步,以绕过这个问题。

类型2:从未看到实现。

类型3:md5哈希:可能发生冲突(128位-2技术字节)

类型4:随机:可能发生碰撞(如抽签)。注意jdk6 impl没有使用一个“真正的”安全随机,因为PRNG算法不是由开发人员选择的,你可以强制系统使用一个“糟糕的”PRNG算法。所以UUID是可预测的。

类型5:sha1哈希:未实现:可能发生冲突(160位-2技术字节)

有人有经验可以分享吗?

type-4 UUID有2^122个可能的值。(规范说,类型损失2位,版本号损失4位。)

假设您每秒生成100万个随机uuid,那么在您的一生中出现重复uuid的几率将微乎其微。为了检测重复,您必须解决每秒将100万个新uuid与之前生成的所有uuid进行比较的问题1!

任何人在现实生活中经历(即实际注意到)一个复制品的机会甚至比消失的小得多……因为寻找碰撞的实际困难。

当然,您通常会使用伪随机数生成器,而不是真正的随机数源。但我认为我们可以确信,如果您使用可信的提供商来提供加密强度随机数,那么它将是加密强度,并且重复的概率将与理想(无偏差)随机数生成器相同。

然而,如果你要使用一个带有“坏掉的”加密随机数生成器的JVM,那么一切都是徒劳的。(这可能包括一些系统上“熵不足”问题的变通方法。或者有人在您的系统或上游对您的JRE进行了修补。)


1 - Assuming that you used "some kind of binary btree" as proposed by an anonymous commenter, each UUID is going to need O(NlogN) bits of RAM memory to represent N distinct UUIDs assuming low density and random distribution of the bits. Now multiply that by 1,000,000 and the number of seconds that you are going to run the experiment for. I don't think that is practical for the length of time needed to test for collisions of a high quality RNG. Not even with (hypothetical) clever representations.