如何在 Java 中生成真正的 UUID?
How to produce a True UUID in Java?
我的印象是 UUID 规范需要一个有保证的、真实的、全局唯一的结果,不是 99.99999999999% 的时间唯一,而是真正 100% 的时间。来自 spec:
A UUID is 128 bits long, and can guarantee
uniqueness across space and time.
看起来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 中有没有办法做到这一点?
因为你的熵受限于你的记忆,你永远无法确保 UUID 是 "guaranteed, true, globally unique result"。不过99.99999999999%已经很不错了
如果您想确保数据库中的值是唯一的,您可以使用递增的简单整数来确保它是唯一的。如果你想使用 UUID 并真正确定它们是唯一的,你只需要在创建时检查它。如果有重复的,就再创建一个,直到它是唯一的。
可能会出现重复,但 IIRC,其中一部分是根据您当前的时间创建的,因此如果您只是每 5 分钟创建一个,您应该是安全的。
UUID 的生成方法有多种。您正在使用的类型完全按照它应该的方式运行。您正在使用 nameUUIDFromBytes
、"Static factory to retrieve a type 3 (name based) UUID based on the specified byte array."
如果给定相同的名称,这将生成相同的 UUID。正如您所发现的,您的循环每次都传入相同的名称,因此您获得相同的 UUID。
在这里查看 Gabe 的建议:Which UUID version to use?
他建议您使用 V4,正如其他人指出的那样,它足以满足任何实际用例。
正如其他人指出的那样,UUID.randomUUID()
返回的 type-4 UUID 可能对于任何实际应用来说都足够独特。不太可能是病态的情况:例如,将 VM 回滚到实时快照,而不重新启动 Java 进程,以便随机数生成器返回到准确的先前状态。
相比之下,类型 3 或类型 5 UUID 的唯一性取决于您输入的内容。
A 类型 1 UUID(基于时间的)在某些限制条件下应该非常 "more" 唯一。 Java 平台不支持生成 type-1 UUID,但我编写了代码(可能未发布)以通过 JNI 调用 UUID 生成库。是18行C和11行Java.
我的印象是 UUID 规范需要一个有保证的、真实的、全局唯一的结果,不是 99.99999999999% 的时间唯一,而是真正 100% 的时间。来自 spec:
A UUID is 128 bits long, and can guarantee uniqueness across space and time.
看起来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 中有没有办法做到这一点?
因为你的熵受限于你的记忆,你永远无法确保 UUID 是 "guaranteed, true, globally unique result"。不过99.99999999999%已经很不错了
如果您想确保数据库中的值是唯一的,您可以使用递增的简单整数来确保它是唯一的。如果你想使用 UUID 并真正确定它们是唯一的,你只需要在创建时检查它。如果有重复的,就再创建一个,直到它是唯一的。
可能会出现重复,但 IIRC,其中一部分是根据您当前的时间创建的,因此如果您只是每 5 分钟创建一个,您应该是安全的。
UUID 的生成方法有多种。您正在使用的类型完全按照它应该的方式运行。您正在使用 nameUUIDFromBytes
、"Static factory to retrieve a type 3 (name based) UUID based on the specified byte array."
如果给定相同的名称,这将生成相同的 UUID。正如您所发现的,您的循环每次都传入相同的名称,因此您获得相同的 UUID。
在这里查看 Gabe 的建议:Which UUID version to use? 他建议您使用 V4,正如其他人指出的那样,它足以满足任何实际用例。
正如其他人指出的那样,UUID.randomUUID()
返回的 type-4 UUID 可能对于任何实际应用来说都足够独特。不太可能是病态的情况:例如,将 VM 回滚到实时快照,而不重新启动 Java 进程,以便随机数生成器返回到准确的先前状态。
相比之下,类型 3 或类型 5 UUID 的唯一性取决于您输入的内容。
A 类型 1 UUID(基于时间的)在某些限制条件下应该非常 "more" 唯一。 Java 平台不支持生成 type-1 UUID,但我编写了代码(可能未发布)以通过 JNI 调用 UUID 生成库。是18行C和11行Java.