使用Python的UUID生成唯一ID,还需要检查重复吗?

19 投票
4 回答
17179 浏览
提问于 2025-04-18 08:12

我正在使用Python的UUID功能来为要存储在数据库中的对象创建唯一的ID:

>>> import uuid
>>> print uuid.uuid4()
2eec67d5-450a-48d4-a92f-e387530b1b8b

我可以放心地认为这个ID确实是唯一的吗?

还是说在接受这个ID之前,我应该再检查一下,确保它在我的数据库中没有被生成过?

4 个回答

0

在个人电脑上生成UUID(通用唯一标识符)的最正确方法是使用uuid4,除了在特定情况下需要使用其他方法外,最好不要用其他方式。


uuid4可以保证与其他电脑生成的UUID是唯一的。

此外,uuid4目前是加密安全的,这意味着即使你在网上公开了你的UUID,随机数生成器和随机性也足够强大,能防止别人猜测你将来可能生成的UUID。不过,这并不是绝对保证,所以如果你的应用需要加密安全,并且你处理的是敏感用户信息,建议使用secrets模块。

  • 需要注意的是,如果你使用的是V1版本的UUID,它是基于时间戳和MAC地址生成的,如果你的UUID在网上被公开,别人可以很容易地猜测未来的时间戳,而且你已经暴露了你的MAC地址,这样就可能会产生重复的UUID。

这个保证是基于UUID中的122位随机性,这使得破解一个UUID的难度相当于破解一个比特币钱包的难度。


  • 版本1:使用时间戳和MAC地址生成的UUID。
    • 如果在同一时间戳生成,它会加1。
    • 特定需求:在查看业务日志时,可以告诉你UUID是何时生成的,以及是哪个机器生成的。
  • 版本2:不使用。
  • 版本3:基于给定数据的MD5哈希生成的UUID。(与SHA1相同)
  • 版本4:使用随机数据生成的UUID。
    • 特定需求:你想要最强的唯一性和安全性保证。
  • 版本5:基于给定数据的SHA1哈希生成的UUID。
    • 特定需求:当你想将UUID与“给定数据”关联时。

使用V4版本时,随机性用于初始化随机数生成器。这包括时间戳、MAC地址,以及系统可以收集的其他信息(如CPU的内部随机数生成器、启动时间、温度读数、磁盘使用情况)。

V1实际上是V4的一种形式,它的随机性仅来自时间戳和MAC地址,随机数生成器的公式是f(x) = x。

关于urandom安全性的细节可以在这里找到。

6

只要你在同一个系统上生成所有的UUID,除非Python的实现有非常严重的问题(我真的无法想象会发生这种事),根据RFC 4122的规定,它们都会是不同的(编辑:如果使用的是版本1、3或5)。

UUID可能出现的问题是,如果两个系统在完全相同的时刻生成UUID,并且:

  • 它们的网络卡使用了相同的MAC地址(这真的很少见),并且你使用的是UUID版本1
  • 或者它们使用了相同的名字,而你使用的是UUID版本3或5
  • 或者它们生成了相同的随机数,而你使用的是UUID版本4(*)

所以,如果你有一个真实的MAC地址,或者使用一个官方的DNS名称,或者一个独特的LDAP DN,你可以放心,生成的UUID将是全球唯一的。

在我看来,如果你想防止你的应用程序受到恶意攻击,试图故意使用一个已经存在的UUID,那么你只需要检查一下唯一性。

编辑:正如Martin Konecny所说,在UUID版本4中,时间戳部分也是随机的,并不是单调递增的。所以发生碰撞的可能性非常有限,但不是零。

6

你应该始终进行重复检查,虽然出现重复的几率不大,但总是有可能会出现重复的情况。

我建议在你的数据库中添加一个重复键的限制,如果出现错误,就重试一下。

13

我会使用 uuid1,因为它在生成UUID时会考虑日期和时间,所以碰撞的可能性为零(除非你同时生成了大量的UUID)。

你实际上可以 反向解析UUID1 的值,从中获取生成它时使用的原始时间。

uuid4 生成的是一个随机ID,碰撞的可能性非常小,但因为它没有使用不断增加的时间作为输入(也没有把它包含在输出的UUID中),所以之前生成的值在未来有(非常)小的几率会再次被生成。

撰写回答