4. Specification (规范)
4.1. Format (格式)
UUID 格式为 16 个八位字节; 下面指定的八个八位字节变体字段的某些位确定更精细的结构.
4.1.1. Variant (变体)
变体字段确定 UUID 的布局.也就是说, UUID 中所有其他位的解释取决于变体字段中位的设置.变体字段由 UUID 的八位字节 8 的可变数量的最高有效位组成.
下表列出了变体字段的内容, 其中字母 "x" 表示 "无关" 值.
| Msb0 | Msb1 | Msb2 | Description (描述) |
|---|---|---|---|
| 0 | x | x | Reserved, NCS backward compatibility (保留, NCS 向后兼容) |
| 1 | 0 | x | The variant specified in this document (本文档中指定的变体) |
| 1 | 1 | 0 | Reserved, Microsoft Corporation backward compatibility (保留, Microsoft Corporation 向后兼容) |
| 1 | 1 | 1 | Reserved for future definition (保留供未来定义) |
4.1.2. Layout and Byte Order (布局和字节顺序)
为了最大限度地减少对八位字节内位分配的混淆, UUID 记录定义仅根据八位字节的整数倍的字段来定义.字段首先呈现最高有效位.
| Field (字段) | Data Type (数据类型) | Octet # (八位字节编号) | Note (注释) |
|---|---|---|---|
| time_low | unsigned 32 bit integer (无符号 32 位整数) | 0-3 | The low field of the timestamp (时间戳的低字段) |
| time_mid | unsigned 16 bit integer (无符号 16 位整数) | 4-5 | The middle field of the timestamp (时间戳的中间字段) |
| time_hi_and_version | unsigned 16 bit integer (无符号 16 位整数) | 6-7 | The high field of the timestamp multiplexed with the version number (时间戳的高字段与版本号复用) |
| clock_seq_hi_and_reserved | unsigned 8 bit integer (无符号 8 位整数) | 8 | The high field of the clock sequence multiplexed with the variant (时钟序列的高字段与变体复用) |
| clock_seq_low | unsigned 8 bit integer (无符号 8 位整数) | 9 | The low field of the clock sequence (时钟序列的低字段) |
| node | unsigned 48 bit integer (无符号 48 位整数) | 10-15 | The spatially unique node identifier (空间唯一的节点标识符) |
UUID 结构 (128 位):
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| time_low |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| time_mid | time_hi_and_version |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|clk_seq_hi_res | clk_seq_low | node (0-1) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| node (2-5) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4.1.3. Version (版本)
版本号在时间戳的最高有效 4 位中 (time_hi_and_version 字段的第 4 位到第 7 位).
下表列出了此 UUID 变体的当前定义版本:
| Msb0-3 | Version (版本) | Description (描述) |
|---|---|---|
| 0001 | 1 | The time-based version specified in this document (本文档中指定的基于时间的版本) |
| 0010 | 2 | DCE Security version, with embedded POSIX UIDs (DCE 安全版本, 嵌入了 POSIX UID) |
| 0011 | 3 | The name-based version specified in this document that uses MD5 hashing (本文档中指定的使用 MD5 哈希的基于名称的版本) |
| 0100 | 4 | The randomly or pseudo-randomly generated version specified in this document (本文档中指定的随机或伪随机生成的版本) |
| 0101 | 5 | The name-based version specified in this document that uses SHA-1 hashing (本文档中指定的使用 SHA-1 哈希的基于名称的版本) |
4.1.4. Timestamp (时间戳)
时间戳是一个 60 位值.对于 UUID 版本 1, 这由协调世界时 (UTC) 表示, 作为自 1582 年 10 月 15 日 00:00:00.00 (格里高利历改革到基督教日历的日期) 以来的 100 纳秒间隔计数.
对于 UUID 版本 3 或 5, 时间戳是从名称构造的 60 位值, 如第 4.3 节所述.
对于 UUID 版本 4, 时间戳是随机或伪随机生成的 60 位值, 如第 4.4 节所述.
4.1.5. Clock Sequence (时钟序列)
对于 UUID 版本 1, 时钟序列用于帮助避免当时钟向后设置或节点 ID 更改时可能出现的重复.
时钟序列必须最初 (即, 在系统的生命周期内一次) 初始化为随机数, 以最小化跨系统的相关性.
对于 UUID 版本 3 或 5, 时钟序列是从名称构造的 14 位值, 如第 4.3 节所述.
对于 UUID 版本 4, 时钟序列是随机或伪随机生成的 14 位值.
4.1.6. Node (节点)
对于 UUID 版本 1, 节点字段由 IEEE 802 MAC 地址组成, 通常是主机地址.对于具有多个 IEEE 802 地址的系统, 可以使用任何可用的地址.
对于 UUID 版本 3 或 5, 节点字段是从名称构造的 48 位值, 如第 4.3 节所述.
对于 UUID 版本 4, 节点字段是随机或伪随机生成的 48 位值.
4.1.7. Nil UUID (空 UUID)
空 UUID 是 UUID 的特殊形式, 指定将所有 128 位设置为零:
00000000-0000-0000-0000-000000000000
4.2. Algorithms for Creating a Time-Based UUID (创建基于时间的 UUID 的算法)
4.2.1. Basic Algorithm (基本算法)
生成基于时间的 UUID 的基本算法:
- 获取系统范围的全局锁
- 读取当前时间
- 获取当前节点 ID
- 如果自上次生成 UUID 以来节点 ID 已更改, 则将时钟序列设置为随机值
- 如果当前时间早于上次时间戳, 则递增时钟序列
- 保存时间戳和节点 ID
- 释放全局锁
- 使用时间戳,时钟序列和节点 ID 格式化 UUID
4.2.2. Generation Details (生成细节)
Timestamp (时间戳): 时间戳是从系统时间构造的 60 位值.时间戳分辨率为 100 纳秒.
Clock Sequence (时钟序列): 时钟序列最初设置为随机值.每次时钟向后移动或节点 ID 更改时, 它都会递增.
Node ID (节点 ID): 节点 ID 通常是 IEEE 802 MAC 地址.
4.3. Algorithm for Creating a Name-Based UUID (创建基于名称的 UUID 的算法)
创建基于名称的 UUID (版本 3 或版本 5) 的算法:
- 分配一个 UUID 作为 "命名空间 ID", 用于从该命名空间中的名称生成的所有 UUID
- 选择 MD5 (版本 3) 或 SHA-1 (版本 5) 作为哈希算法
- 将名称转换为规范的八位字节序列
- 计算命名空间 ID 与名称连接的哈希
- 将八位字节零到 15 设置为哈希的八位字节零到 15
- 将八位字节 6 的四个最高有效位 (第 12 位到第 15 位) 设置为适当的版本号
- 将八位字节 8 的两个最高有效位 (第 6 位和第 7 位) 分别设置为零和一
4.4. Algorithms for Creating a UUID from Truly Random or Pseudo-Random Numbers (从真随机或伪随机数创建 UUID 的算法)
版本 4 UUID 旨在从真随机或伪随机数生成 UUID.
算法如下:
- 将所有位设置为随机 (或伪随机) 选择的值
- 将八位字节 6 的四个最高有效位 (第 12 位到第 15 位) 设置为 4 位版本号 (0100 二进制)
- 将八位字节 8 的两个最高有效位 (第 6 位和第 7 位) 分别设置为零和一
⚠️ 位掩码逻辑精确描述:
对于版本 4 UUID, 必须执行以下精确的位操作:
- 版本位设置 (Version Bits): 八位字节 6 的位 12-15 必须设置为
0100(二进制), 即十进制值 4 - 变体位设置 (Variant Bits): 八位字节 8 的位 6-7 必须设置为
10(二进制) - 随机位 (Random Bits): 所有其他 122 位必须从加密安全的随机源或高质量的伪随机数生成器获取
实现示例 (伪代码):
uuid[6] = (uuid[6] & 0x0F) | 0x40; // 设置版本为 4 (0100xxxx)
uuid[8] = (uuid[8] & 0x3F) | 0x80; // 设置变体为 10xxxxxx
4.5. Node IDs that Do Not Identify the Host (不标识主机的节点 ID)
本节描述了生成不标识主机的节点 ID 的替代方案:
-
Random Node ID (随机节点 ID): 将节点 ID 的第一个八位字节的最低有效位设置为 1 (多播位).这将 UUID 标记为不基于真实 MAC 地址.
-
Persistent Random Node ID (持久随机节点 ID): 生成一次随机节点 ID 并存储以供重用.这在保持隐私的同时提供跨重启的一致性.
注意: 有关详细的实现示例和完整算法, 请参阅官方 RFC 4122 规范和附录 A.