我理解docs.
中两者之间的差异 uuid1()
:
从主机ID,序列号和当前时间生成UUID
uuid4()
:
生成随机UUID。
所以uuid1
使用机器/序列/时间信息来生成UUID。使用每种产品的优缺点是什么?
我知道uuid1()
可能存在隐私问题,因为它基于机器信息。我想知道在选择其中一个时是否更加微妙。我现在只使用uuid4()
,因为它是一个完全随机的UUID。但我想知道我是否应该使用uuid1
来减少碰撞的风险。
基本上,我正在寻找人们关于使用一对一的最佳实践的提示。谢谢!
答案 0 :(得分:237)
uuid1()
不会产生任何冲突(假设您不会同时创建太多冲突)。如果重要的是uuid
和计算机之间没有连接,我就不会使用它,因为mac地址被用来使它在计算机上变得独一无二。
您可以通过在不到100ns的时间内创建超过2个 14 uuid1来创建重复项,但对于大多数用例来说这不是问题。
如你所说, uuid4()
生成随机UUID。碰撞的可能性确实非常小真的。足够小,你不应该担心它。问题是,一个坏的随机数生成器使它更容易发生冲突。
This excellent answer by Bob Aman很好地总结了它。 (我建议阅读整个答案。)
坦率地说,在一个应用程序空间中 没有恶意的演员, 地球上所有生命的灭绝都会消失 很久才发生 碰撞,即使在版本4 UUID上, 即使你产生了不少 每秒UUID。
答案 1 :(得分:31)
当您在不同的计算机上生成UUID 时,您可能会认为uuid1()
而不是uuid4()
的一个实例,例如,当多台计算机上的多个联机事务处理以进行扩展时目的。
在这种情况下,例如,由于伪随机数生成器的初始化方式选择不当而导致冲突的风险,以及可能产生的更多UUID,更有可能创建重复的ID
uuid1()
的另一个好处是,在这种情况下,隐含地记录了最初生成每个GUID的机器(在UUID的“节点”部分)。只有调试时,这个和时间信息才有用。
答案 2 :(得分:5)
使用uuid1
时需要注意的一点是,如果使用默认调用(不提供clock_seq
参数),则有可能遇到冲突:您只有14位随机性(生成18位) 100ns内的条目让你有大约1%的碰撞机会看到生日悖论/攻击)。在大多数用例中永远不会出现此问题,但在时钟分辨率较差的虚拟机上,它会咬你。
答案 3 :(得分:3)
也许没有提到的是当地的东西。
MAC地址或基于时间的排序(UUID1)可以提高数据库性能,因为与那些随机分布的数据(UUID4)相比,对数字进行更接近排序的工作要少(参见here)。
第二个相关问题是,即使原始数据丢失或未明确存储,使用UUID1在调试中也很有用(这显然与OP提到的隐私问题相冲突。)
答案 4 :(得分:1)
除了接受的答案之外,还有第三种选择在某些情况下很有用:
带有随机MAC的你可以在v1和amp;之间进行混合v4通过故意生成带有随机广播MAC地址的v1 UUID(这是v1规范允许的)。生成的v1 UUID是时间相关的(如常规v1),但缺少所有特定于主机的信息(如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)
(注意:我有一个更长+更快的版本,直接创建UUID对象;如果有人想要可以发布)
如果大量呼叫/秒,这有可能耗尽系统随机性。您可以使用stdlib random
模块(它可能也会更快)。但是警告:在攻击者确定RNG状态之前,只需要几百个UUID,从而部分预测未来的UUID。
import random
from uuid import uuid1
def uuid1mc_insecure():
return uuid1(random.getrandbits(48) | 0x010000000000)