使用UUID生成唯一ID是否真的是唯一的?

10

我想生成类似于Java中的自动递增的唯一ID。之前我使用了当前纳秒数,但由于两个数据在同一纳秒内到达,导致冲突。UUID能解决上述问题吗?

注意:在我的项目中,每分钟甚至可以获得10000行记录,我将把这些记录和UID存储到表中。可能会出现一种情况,即我停止产品并在一段时间后重新启动它...那么在这种情况下,UUID类如何将以前生成的UID(我存储在数据库中)与即将创建的新UID(尚未转储到数据库中)进行区分?

3个回答

12

虽然UUID并不能保证唯一性,但是出现重复的概率极低。请参考随机UUID重复概率

对于您的应用程序来说,使用UUID是有意义的,但是为了防范极其罕见的情况,您可能需要处理重复问题。


你能否请明确一下“UUID根据时间戳生成随机ID”这句话的意思。既然如此,它怎么可能不保证唯一性呢? - vijayasankarj
1
根据文档,UUID是使用加密随机数生成器生成的。由于UUID长度为128位,它是有限大小的,有极小的概率会再次生成相同的UUID,但这不是实际上需要担心的事情。 - AbdullahC
在我的项目中,我甚至可以每分钟获取10000行记录,并将这些记录连同UIDS一起转储到表中。可能会出现这样的情况,即我会停止我的产品并在一段时间后重新启动它...因此,在这种情况下,UUID类如何将以前生成的UID(我存储在数据库中的UID)与即将创建的新UID(尚未转储到数据库中)进行澄清? - vijayasankarj
1
那就是加密随机数生成器的工作方式。它们生成一个(伪)随机数字,范围足够大,使得碰撞几乎不成问题。 - AbdullahC

8

我严重怀疑你能在调用System.nanoTime()时获得两个记录的时间在同一纳秒内,因为System.nanoTime()的调用需要超过100ns。更可能的情况是您的时钟没有纳秒精度。

然而,如果你重新启动你的服务器,你可以得到重复的nanoTime()。

解决这个问题的一种方法是使用

AtomicLong counter = new AtomicLong(System.currentTimeMillis()*1000);

long id = counter.incrementAndGet();

// something like ctz9yamgu8
String id = Long.toString(counter.incrementAndGet(), 36);

应用程序重新启动时,这将启动一个计数器,并且在重新启动之间不会重叠,除非您每秒维持超过一百万个ID(在实例的生命周期内)。

注意:这仅适用于每个实例。多个服务器需要使用不同的方法。


3

这个页面似乎对UUID的性质存在一些混淆。

请阅读Wikipedia页面,您将会看到有不同的UUID版本

您问道:

UUID是否解决了上述问题?

是的,UUID值确实解决了您的问题。

时空中的一个点

最初的版本1表示时空中的一个点,永远不会重复。

版本1通过使用生成它的计算机(空间中的一个点)的MAC地址,结合当前时刻和在注意到计算机时钟变化时递增的任意数字来实现。由于计算机现在具有内置电池和网络连接到时间服务器,所以时钟不再是一个问题。通过组合这些元素,几乎不可能发生碰撞。

由于跟踪和披露MAC地址和时刻可能涉及安全和隐私问题,一些人可能不想使用此版本。例如,Java从其UUID类中省略了生成版本1。

值得一提的是,像Postgres这样更强大的数据库服务器可以生成包括版本1在内的UUID值。您可以选择在数据库服务器上生成UUID,而不是在应用程序中生成。

随机

常用的版本之一是 版本4,其中的128位中有122位是随机生成的。如果使用密码学强度随机生成器,这是相当有效的。该版本与版本1相比具有更高的碰撞概率。但对于大多数实际情况来说,基于随机数的UUID是完全可靠的。


我喜欢你的回答,@Basil Bourque。 - Mo'ath Alshorman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接