我的印象是,UUID规范需要一个有保证的,真实的,全球唯一的结果,而不是99.99999999999%的独特时间,但真正100%的时间。来自spec:
UUID长128位,可以保证 空间和时间的独特性。
看起来java只支持UUID规范的V3和V4。 V4并不是真正独一无二的。使用nameUUIDFromBytes
的V3实现,以下结果是重复的,因为计算机太快(编辑:循环到10并且调用new Date().getTime()
将产生重复,因为计算机循环比new Date().getTime()
快可以在每次迭代时产生不同的值):
String seed;
for (int i = 0; i < 10; i++) {
seed = "<hostname>" + new Date().getTime();
System.out.println(java.util.UUID.nameUUIDFromBytes(seed.getBytes()));
}
我错误地假设UUID是100%唯一的,并且它实际上只是唯一但不完美如此?无论如何在Java中这样做?
答案 0 :(得分:4)
有不同的UUID生成方法。你正在使用的那种行为完全符合它应该的行为。您正在使用nameUUIDFromBytes
,“静态工厂根据指定的字节数组检索类型3(基于名称的)UUID。”
如果给出相同的名称,则生成相同的UUID。正如您所发现的,您的循环每次都传递相同的名称,因此您获得相同的UUID。
在这里查看Gabe的建议:Which UUID version to use? 他建议你使用V4,正如其他人指出的那样,V4足以应付任何真实的用例。
答案 1 :(得分:2)
因为您的熵仅限于您的记忆,所以您永远无法确保UUID是“保证,真实,全球唯一的结果”。但是,99.99999999999%已经相当不错了。
如果要确保数据库中的唯一值,可以使用一个递增的简单整数,以确保它是唯一的。如果你想使用UUID并且确定它们是唯一的,你只需要在创建时检查它。如果有重复,只需创建另一个,直到它是唯一的。
可能会发生重复,但IIRC,其中一部分是根据您当前的时间创建的,所以如果您只是每5分钟创建一个,那么您应该是安全的。
答案 2 :(得分:0)
正如其他人所指出的那样,UUID.randomUUID()
返回的4型UUID可能对任何实际应用都足够独特。它不可能是病态的情况:例如,将VM回滚到实时快照,而不重新启动Java进程,以便随机数生成器返回到精确的先前状态。
相比之下,type-3或type-5 UUID只与你投入的UUID一样独特。
类型1 UUID(基于时间)应该非常轻微&#34;更多&#34;独特的,在某些限制下。 Java平台不包括对生成类型1 UUID的支持,但是我编写了代码(可能未发布)以通过JNI调用UUID生成库。这是18行C和11行Java。