UUID(Universally Unique Identifier,通用唯一标识符)是一种 128 位标识符,用于在分布式系统中生成具有极低碰撞概率的唯一 ID。
UUID 最初源于 Apollo Computer 的 NCS(Network Computing System),随后进入 OSF 的 DCE(Distributed Computing Environment)。微软的 GUID(Globally Unique Identifier)也沿用了这一体系。
现代 UUID 的规范主要由 IETF RFC 9562 定义,它于 2024 年发布并取代了 RFC 4122。与此同时,UUID 也被 ITU-T X.667 / ISO/IEC 9834-8 标准化。
UUID 固定为 128 bit,即 16 字节。通常使用 32 个十六进制字符,并按照 8-4-4-4-12 的形式表示:
d09abf7e-3e39-11ec-9dbc-b1755772e461
历史
UUID 的发展大致经历了以下几个阶段:
-
Apollo NCS
- Apollo Computer 的 Network Computing System 最早提出类似 UUID 的标识机制。
- 采用时间、主机信息等数据生成标识符。
-
OSF DCE
- Open Software Foundation 将相关机制纳入 DCE。
- DCE UUID 成为后来 UUID 标准的重要基础。
- UUIDv1、UUIDv2 等设计均与这一时期有关。
-
Microsoft GUID
- Microsoft 在 Windows 体系中采用 GUID。
- GUID 与 UUID 在结构和生成机制上高度兼容。
-
IETF RFC 4122
- 2005 年发布,系统描述了 UUID 的格式、Variant 和 Version。
- UUIDv1~v5 成为互联网软件中广泛使用的 UUID 版本。
-
RFC 9562
- 2024 年发布,正式废止并取代 RFC 4122。
- 新增并标准化 UUIDv6、UUIDv7、UUIDv8。
- 对 UUIDv1~v5 进行了重新整理。
- 当前开发中应优先参考 RFC 9562,而不是 RFC 4122。
语法
UUID 的规范表示形式为:
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
其中:
M:Version(版本),占 4 bit,表示 UUID 的生成规则。N:Variant(变体),通过最高有效位确定 UUID 属于哪套格式规范。- 其余位由具体 UUID Version 定义。
例如:
d09abf7e-3e39-11ec-9dbc-b1755772e461
↑ ↑
Version Variant
UUID 的 Version 和 Variant 是两个不同概念:
- Version:采用什么生成算法,相当于大分类下的二级分类
-
Variant:采用什么 UUID 格式体系,相当于大分类
Variant 编码 含义 0 0xxxNCS / Apollo UUID 1 10xxRFC 4122 / RFC 9562 UUID 2 110xMicrosoft GUID 兼容格式 3 111x保留 实际开发中基本只需要关注 Variant 1。
RFC 4122 使用10xx,第四组第一个十六进制字符只能是:8/9/a/b,RFC 9562 继续采用这一 Variant。
现代 UUID 基本都是 RFC 9562 Variant + 某个 Version。
UUID Version
Version 占 4 bit。
常见版本包括:
| Version | 核心生成方式 | 是否确定性 | 是否有序 | 是否随机 | 主要特点 |
|---|---|---|---|---|---|
| Nil UUID | 全 0 | — | — | ❌ | 特殊值,表示空 UUID |
| UUID v1 | 时间戳 + Node ID + Clock Sequence | ❌ | ⚠️ 时间相关 | ❌ | 传统时间型 UUID,可能暴露时间和节点信息 |
| UUID v2 | 时间戳 + DCE Security 信息 | ❌ | ⚠️ 时间相关 | ❌ | v1 的 DCE Security 变体,现代系统很少使用 |
| UUID v3 | MD5(namespace + name) | ✅ | ❌ | ❌ | 相同 Namespace + Name 始终生成相同 UUID |
| UUID v4 | 随机数 | ❌ | ❌ | ✅ | 最常见的随机 UUID,生成简单 |
| UUID v5 | SHA-1(namespace + name) | ✅ | ❌ | ❌ | 确定性 ID,v3 的 SHA-1 版本 |
| UUID v6 | 重排后的 v1 时间戳 + Node ID | ❌ | ✅ 时间有序 | ❌ | 优化时间排序和数据库索引 |
| UUID v7 | Unix 时间戳 + 随机数 | ❌ | ✅ 时间有序 | ✅ | 现代推荐方案,兼顾时间排序与随机性 |
| UUID v8 | 自定义 | ⚠️ 取决于实现 | ⚠️ 取决于实现 | ⚠️ 取决于实现 | 为应用自定义 UUID 格式保留 |
Nil UUID
Nil UUID 是一个特殊值,不属于某个具体 Version:
00000000-0000-0000-0000-000000000000
128 bit 全部为 0。
通常用于表示:
- 未设置
- 空 UUID
- 不存在
- 默认值
UUIDv1
UUIDv1 基于时间和 Node ID 生成。
主要组成:
60 bit timestamp
14 bit clock sequence
48 bit node
总计:
60 + 14 + 48 = 122 bit
剩余:
4 bit version
2 bit variant
完整布局:
32 bit time_low
16 bit time_mid
4 bit version + 12 bit time_hi
2 bit variant + 14 bit clock_seq
48 bit node
因此:
32 + 16 + 16 + 16 + 48 = 128 bit
时间戳
UUIDv1 使用 UUID Epoch:
1582-10-15 00:00:00
即公历格里高利历开始的日期。
时间单位为:
100 ns
因此时间戳表示的是:
从 1582-10-15 00:00:00 开始经过了多少个 100 ns 间隔。
Unix 时间转换时,需要加上:
0x01b21dd213814000
即 UUID Epoch 与 Unix Epoch:
1582-10-15
↓
1970-01-01
之间的 100 ns 间隔数量。
Python 标准库中的核心计算逻辑类似:
nanoseconds = time.time_ns()
timestamp = (
nanoseconds // 100
+ 0x01b21dd213814000
)
Node
UUIDv1 通常使用 48 bit Node ID,传统实现一般使用机器的 MAC 地址。
因此 UUIDv1 可能泄露:
- 生成机器的 MAC 地址
- UUID 生成的大致时间
这也是后来 UUIDv6/v7 更受欢迎的重要原因之一。
UUIDv2
UUIDv2 是 DCE Security UUID。
它基于 UUIDv1,但将部分字段替换为本地域信息。
例如 POSIX 系统中:
Local Domain 0 → UID
Local Domain 1 → GID
UUIDv2 并没有被 RFC 4122 详细定义,RFC 4122 仅保留了相关描述。
因此现代开发中基本不会使用 UUIDv2。
UUIDv3
UUIDv3 根据 Namespace + Name 生成 UUID。
核心算法:
MD5(namespace || name)
然后修改其中的:
Version
Variant
相关 bit,使其符合 UUIDv3 格式。
UUIDv3 的特点是:
同一个 Namespace + Name 永远产生相同 UUID。
因此它不是随机 ID,而是一个确定性 ID。
RFC 定义了几个标准 Namespace:
| Namespace | UUID |
|---|---|
| DNS | 6ba7b810-9dad-11d1-80b4-00c04fd430c8 |
| URL | 6ba7b811-9dad-11d1-80b4-00c04fd430c8 |
| OID | 6ba7b812-9dad-11d1-80b4-00c04fd430c8 |
| X.500 DN | 6ba7b814-9dad-11d1-80b4-00c04fd430c8 |
例如:
UUIDv3(DNS, "example.com")
可以得到一个稳定的 UUID。
UUIDv4
UUIDv4 是最常见的随机 UUID。
除了:
4 bit version
2 bit variant
之外,其余位由随机数或伪随机数填充(122 bit)。
UUIDv4 的形式:
xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
其中:
y ∈ {8, 9, a, b}
例如:
550e8400-e29b-41d4-a716-446655440000
↑
v4
理论上 UUIDv4 有 2^122 种可能值,在使用高质量随机数生成器的情况下,碰撞概率极低。
UUIDv5
UUIDv5 与 UUIDv3 唯一的区别就是采用 SHA-1 算法替代 MD5 算法。
UUIDv5 通常比 UUIDv3 更推荐,因为 SHA-1 的安全性明显优于 MD5。
不过 UUIDv5 的主要需求是确定性标识,并不是密码学安全哈希。
UUIDv6
UUIDv6 是对 UUIDv1 的重新布局。
UUIDv1 的时间戳被拆成:
time_low
time_mid
time_hi
导致 UUID 的字典序并不能直接对应时间顺序。
UUIDv6 将 60 bit 时间戳重新排列,使其高位时间戳首先出现,从而获得更好的时间有序性。
逻辑布局为:
32 bit timestamp_high
4 bit version + 12 bit timestamp_mid
16 bit timestamp_low
2 bit variant + 14 bit clock_seq
48 bit node
因此 UUIDv6 更适合:
- 数据库索引
- B-Tree
- 日志 ID
- 分布式事件 ID
- 按生成时间排序
UUIDv6 仍然可能包含 Node ID,因此仍存在暴露机器信息的问题。
UUIDv7
UUIDv7 是现代系统非常值得优先考虑的 UUID 类型。
其结构为:
48 bit Unix timestamp in milliseconds
4 bit version
12 bit rand_a
2 bit variant
62 bit rand_b
布局:
xxxxxxxx-xxxx-7xxx-yxxx-xxxxxxxxxxxx
其中前 48 bit 是毫秒时间戳,因此 UUIDv7 的前缀天然具有时间顺序。
与 UUIDv1/v6 相比,UUIDv7 不包含 MAC 地址。
它同时具有:
- 时间可排序(同一毫秒内可能就乱序了)
- 不暴露 MAC 地址
- 跨系统容易生成
- 随机部分空间大
- 适合数据库索引
因此在现代业务系统中,如果需要全局唯一 + 大致按时间排序,UUIDv7 通常是比 UUIDv4 更好的默认选择。
UUIDv8
UUIDv8 是 RFC 9562 提供的自定义 UUID。
它允许应用程序在规定的 Version 和 Variant 框架下,自定义剩余字段。
基本形式:
xxxxxxxx-xxxx-8xxx-yxxx-xxxxxxxxxxxx
其中:
Version = 8
Variant = RFC 9562
其余字段由应用自行定义。
UUIDv8 适合:
- 企业内部 ID 标准
- 特定业务字段编码
- 自定义分布式 ID
- 与现有系统兼容
但如果没有明确需求,通常不建议自行设计 UUIDv8 格式。
现代 UUID 应该怎么选?
实际工程中,可以简单按照下面的规则选择:
| 需求 | 推荐 |
|---|---|
| 唯一性(随机) | UUIDv4 |
| 时间有序(高精度) | UUIDv6 |
| 时间有序 + 唯一性(折中) | UUIDv7 |
| Namespace + Name 确定性 ID | UUIDv5 |