通用唯一标识符 (UUIDS) 是 128 位数字,由 16 个八位字节组成并表示为 32 个 base-16 字符,可用于识别计算机系统中的信息。该规范最初由 Microsoft 创建并由IETF和ITU 标准化。
UUID 通常用于识别需要在系统或其网络中唯一的信息。它们的唯一性和低重复概率使它们可用作数据库中的关联键和组织内物理硬件的标识符。UUID 的好处之一是它们不需要由中央机构颁发,而是可以独立生成,然后在给定系统中使用,而不会怀疑重复。或碰撞,UUID 已在别处生成。Apple、Microsoft、Samsung 和其他公司使用由 IETF 规范或专有变体定义的 UUID 来识别和跟踪内部硬件和销售给消费者的硬件。
有 5 种不同版本的 UUID,不包括 Nil UUID 版本,这是一种特殊情况的 UUID,其所有字节都设置为 0,并且大多数包含一些变体,允许特定于 Microsoft 等供应商的特殊情况。版本 1 和 2 使用基于时间的源(来自系统时钟的 60 位时间戳)以获得随机性。版本 1 和 2 实际上是相同的,只是在后一个版本中,时钟序列的最低有效位被替换为系统特定的标识符。由于这个和其他原因,大多数实现都省略了第 2 版。第 1 版是最常用的 UUID 版本。
版本 3 和 5 是通过散列名称或命名空间标识符并分别使用生成的散列 MD5 或 SHA-1 作为唯一性来源而不是版本 1 和 2 中基于时间的来源生成的。它们旨在生成来自名称的 UUID,这些名称来自某个名称空间,并且在某个名称空间中是唯一的。名称和名称空间的概念应作广义解释,而不限于文本名称。例如,某些名称空间是域名系统、URL、ISO 对象 ID (OID)、X.500 可分辨名称 (DN) 和编程语言中的保留字。
版本 4 使用随机或伪随机源而不是时间或命名空间派生的源,因为它的唯一性。版本 3、4 和 5 使用它们各自的源生成 60 位的唯一输出,用于代替版本 1 和 2 中使用的时间戳位。
为了展示 UUID 是如何派生的,我们将介绍如何创建版本 1 UUID。对于版本 3 到 5,下面提到的时钟序列源应替换为各自的源。V1 UUID 字符串派生为 6 个字段的有序序列,从而使 ID 具有很大(但不是非零)完全唯一的机会。UUID 记录以大端方式从以下来源派生,如下所示:
TimeLow: 当前 UTC 时间戳低 32 位整数值的 4 个字节(8 个十六进制字符)
TimeMid: 当前 UTC 时间中间 16 位整数值的 2 个字节(4 个十六进制字符)
TimeHighAndVersion: 2 字节(4 个十六进制字符)包含 4 位 UUID 版本(最高有效位)和当前 UTC 时间的高剩余 12 位的整数值(时间戳由 60 位组成)
ClockSequenceHiAndRes && ClockSequenceLow: 2 字节(4 个十六进制字符),其中 1 到 3(有效)位包含正在使用的 UUID 版本的“变体”,其余位包含时钟序列。如果系统中有多个 UUID 生成器,或者生成器的系统时钟设置向后或前进速度不够快,则时钟序列用于帮助避免冲突。有关更改节点 ID 和其他冲突注意事项的更多信息,请参阅IETF RFC 的第 4.1.5节
Node : 6 个字节(12 个十六进制字符),代表 48 位“节点 ID”,通常是生成它的主机硬件的 MAC 地址。
这会产生一个看起来像这样的字符串,例如:
123e4567-e89b-12d3-a456-426655440000
为了进一步分解是什么让我们相信为什么给定的 UUID 最有可能是唯一的,让我们再看看不同 UUID 版本的 UUID 数据的来源:
对于这些版本,我们有 74 位时间数据,60 位来自时间戳,14 位来自时钟序列。除此之外,我们还有 48 位节点 ID,它可以是 MAC,或者在某些情况下我们可能不想公开它或节点没有 MAC,48 位随机或伪随机位。理想情况下(对于 UUID 版本,不适合我们)但是,如果我们有 MAC,并且结合时间戳和时钟序列,我们将获得一个与空间中的单个点(节点 MAC)和时间(时间戳)相关的 ID和时钟序列)。如果理想情况成立,一个节点能够生成 274(18 个十六进制),但如果没有给定 MAC,我们有额外的 48 位唯一性,为一个节点生成 2122 个(5.3 十进制)可能的 UUID。
如果您希望在系统的命名空间中以 UUID 格式存储“可命名”信息和数据的唯一标识符,并确保在您的系统中不会出现重复的资源名称,那么这是要使用的版本。根据规范,首选版本 5,因为它使用 SHA-1。
最“独特”的版本。与其他版本一样,使用 4 位表示版本,根据变体使用 2 位或 3 位表示 UUID 的变体。这留下了 2122 (5.3 × 1036),或者,对于 v4 变体 2,可能的唯一 ID 的一半减少了一个随机位。碰撞的可能性仍然非常小。
在同一节点上同时生成两个相同的 UUID 时发生碰撞的可能性非常小,并且可以使用生日问题来计算碰撞概率。例如,如果我们有 68,719,476,736 个具有 74 个随机位的 UUID,则重复的概率为 0.1175030974154045,但如果我们有 122 个随机位,则概率为 0.0000000000000004 。如果用户使用单个节点为系统生成所有 UUID,他们可能希望考虑使用 UUID 版本 4 而不是 1,因为冲突的机会要大得多。