UUID

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 的发展大致经历了以下几个阶段:

  1. Apollo NCS

    • Apollo Computer 的 Network Computing System 最早提出类似 UUID 的标识机制。
    • 采用时间、主机信息等数据生成标识符。
  2. OSF DCE

    • Open Software Foundation 将相关机制纳入 DCE。
    • DCE UUID 成为后来 UUID 标准的重要基础。
    • UUIDv1、UUIDv2 等设计均与这一时期有关。
  3. Microsoft GUID

    • Microsoft 在 Windows 体系中采用 GUID。
    • GUID 与 UUID 在结构和生成机制上高度兼容。
  4. IETF RFC 4122

    • 2005 年发布,系统描述了 UUID 的格式、Variant 和 Version。
    • UUIDv1~v5 成为互联网软件中广泛使用的 UUID 版本。
  5. 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 0xxx NCS / Apollo UUID
    1 10xx RFC 4122 / RFC 9562 UUID
    2 110x Microsoft 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
如果你有魔法,你可以看到一个评论框~