什么时候应该在python中使用uuid.uuid1()和uuid.uuid4()?

我理解这两个文件之间的差异。

uuid1()
从主机ID,序列号和当前时间生成一个UUID

uuid4()
生成一个随机的UUID。

所以uuid1使用机器/序列/时间信息来生成一个UUID。 各自使用的优缺点是什么?

我知道uuid1()可能有隐私问题,因为它是基于机器信息。 我不知道在select其中一个时还有什么更微妙的地方。 我现在只是使用uuid4() ,因为它是一个完全随机的UUID。 但是我想知道是否应该使用uuid1来减less碰撞风险。

基本上,我正在寻找人们使用一个和另一个最佳做法的技巧。 谢谢!

uuid1()保证不会产生任何冲突(假设你不会同时创build太多的冲突)。 如果在uuid和计算机之间没有连接是很重要的,那么我不会使用它,因为mac地址被用来使它在计算机之间唯一。

您可以通过在小于100ns内创build超过2 14个 uuid1来创build重复项,但对于大多数使用情况来说这不是问题。

如你所说, uuid4()产生一个随机的UUID。 碰撞的可能性确实非常小。 够小,你不应该担心。 问题是,一个坏的随机数发生器使它更有可能发生冲突。

鲍勃·阿曼(Bob Aman)的这个出色的答案很好地总结了这一点。 (我build议阅读完整的答案。)

坦率地说,在没有恶意行为的单一应用程序空间中,即使在第4版UUID中,即使您每秒生成不lessUUID,地球上所有生命的灭绝也会在发生碰撞之前发生。

当您考虑使用uuid1()而不是使用uuid4() 时,一种情况是在单独的计算机上生成UUID时 ,例如在多台计算机上处​​理多个联机事务时出于扩展目的。

在这种情况下,例如由于伪随机数生成器被初始化的方式select差而导致冲突的风险,并且所产生的UUID的数量可能更高,使得更有可能创build重复的ID。

在这种情况下, uuid1()另一个兴趣是每个GUID最初产生的机器被隐式logging(在UUID的“节点”部分)。 这和时间信息,只有在debugging时才有帮助。

我的团队使用UUID1进行数据库升级脚本时遇到了麻烦,我们在几分钟内生成了约120k个UUID。 UUID冲突导致违反主键约束。

我们升级了100多台服务器,但是在我们的Amazon EC2实例上,我们遇到了几次这个问题。 我怀疑糟糕的时钟分辨率和切换到UUID4解决了我们。

使用uuid1时需要注意的一点是,如果使用默认调用(不给clock_seq参数),你有机会碰撞:你只有14位随机性(在100ns内产生18个条目,给你1%的机会碰撞见生日悖论/攻击)。 这个问题在大多数情况下都不会发生,但是在时钟分辨率较差的虚拟机上,它会咬你的。

也许没有提到的是当地的东西。

MAC地址或基于时间的sorting(UUID1)可以提高数据库的性能,因为比起那些随机分布(UUID4)(参见这里 )更紧密地sorting数字的工作量更小。

第二个相关的问题是,即使原始数据丢失或者没有明确存储(这显然与OP提到的隐私问题相冲突),使用UUID1在debugging中也是有用的。

除了被接受的答案之外,还有第三个选项在某些情况下可能有用:

v1随机MAC(“v1mc”)

您可以通过故意生成v1 UUID和随机广播MAC地址(这是v1规范允许的),在v1和v4之间进行混合。 由此产生的v1 UUID与时间有关(如正常v1),但缺less所有主机特定的信息(如v4)。 它在碰撞阻力方面也比较接近v4:v1mc = 60位时间+ 61个随机位= 121个唯一位; v4 = 122个随机位。

我遇到的第一个地方是Postgres的uuid_generate_v1mc()函数。 我已经使用了下面的python等价物:

 from os import urandom from uuid import uuid1 _int_from_bytes = int.from_bytes # py3 only def uuid1mc(): # NOTE: The constant here is required by the UUIDv1 spec... return uuid1(_int_from_bytes(urandom(6), "big") | 0x010000000000) 

(注意:我有一个更长的+更快的版本,可以直接创buildUUID对象;如果有人愿意,可以发布)


在每秒大量的呼叫的情况下,这有可能耗尽系统随机性。 你可以使用stdlib random模块(它可能会更快)。 但是要警惕:在攻击者能够确定RNG状态之前,只需要几百个UUID,从而部分预测未来的UUID。

 import random from uuid import uuid1 def uuid1mc_insecure(): return uuid1(random.getrandbits(48) | 0x010000000000)