什么是 UUID?格式、版本以及 UUID 与 GUID 的区别

UUID(Universally Unique Identifier,通用唯一识别码)是一个 128 位的数字,用来标识数据,而不必向中央服务器申请下一个可用 ID。它通常写成 36 个字符:32 个十六进制数字,按 8-4-4-4-12 分成五组,例如 f47ac10b-58cc-4372-a567-0e02b2c3d479。该格式由 RFC 9562(2024 年 5 月)定义,它取代了 RFC 4122。

免费试用:UUID 生成器 免费使用,无需注册账号。

那么,什么是 UUID 最常见的用途?任何系统都可以自行生成 UUID,即使离线也可以,而且几乎可以确定不会有别人生成同样的值。因此 UUID 常被用作数据库主键、文件名、请求 ID 和消息 ID。本文讲解 UUID 的格式、各个版本、真实的碰撞概率、UUID 与 GUID 的区别,以及如何在 v4 和 v7 之间选择。想边读边试,可以在新标签页中打开免费的 UUID 生成器。

什么是 UUID?它由哪些部分组成(8-4-4-4-12 格式)

128 位就是 16 个字节。每个字节写成两个十六进制数字,共 32 位数字,加上四个连字符,文本形式就是 36 个字符。其中有两个位置含义固定:

f47ac10b-58cc-4372-a567-0e02b2c3d479
              ^    ^
              |    +-- 第 17 位 "a":变体(8、9、a 或 b = RFC 9562)
              +------- 第 13 位 "4":版本 4(随机)

由于这 6 位是固定的,随机的版本 4 UUID 含有 128 − 6 = 122 个随机位。十六进制字母可以大写、小写或混写,所以 F47AC10B-… 和 f47ac10b-… 是同一个 UUID;最常见的习惯是小写。

UUID 版本:v1 到 v8、Nil 和 Max

RFC 9562 定义了八个版本和两个特殊值:

版本 构成方式 常见用途
v1 60 位时间戳(自 1582 年起以 100 纳秒为单位)+ 时钟序列 + 节点 ID,传统上是 MAC 地址 旧系统
v2 DCE 安全版本,RFC 中未详细定义 很少使用
v3 对命名空间 UUID 和名称做 MD5 哈希 可重现的 ID(优先用 v5)
v4 122 个随机位 通用默认选择
v5 对命名空间 UUID 和名称做 SHA-1 哈希 由名称生成可重现的 ID
v6 与 v1 字段相同,但重新排列使时间戳可排序 从 v1 升级
v7 48 位 Unix 毫秒时间戳 + 随机位 数据库主键、可排序 ID
v8 自定义布局,只固定版本和变体 厂商自定义格式
Nil 00000000-0000-0000-0000-000000000000 表示"无值"的占位符
Max ffffffff-ffff-ffff-ffff-ffffffffffff 哨兵值或上界

基于名称的版本是确定性的。DNS 命名空间加上名称 example.com,无论在哪台机器、哪种语言中,都会得到 v5 UUID cfbff0d1-9375-5685-968c-48ce8b15ae17。当同样的输入必须始终对应同一个 ID 时,就用它们。

版本 7 的 UUID 把时间放在最前面。下面这个例子生成于 2026-09-24 12:00:00 UTC,即 Unix 纪元之后 1,790,251,200,000 毫秒,十六进制为 0x01a0d3496e00:

01a0d349-6e00-7c3f-9d21-4b6e8a1f0c57
^^^^^^^^^^^^^ ^    ^
|             |    +-- 变体位 "9"
|             +------- 版本 7
+--------------------- 48 位毫秒时间戳

其余 74 位是随机数(有些库会把其中一部分用作计数器)。

UUID 是唯一的吗?v4 的碰撞概率

UUID 并不保证唯一,只是以压倒性的概率唯一。122 个随机位意味着共有 2^122 ≈ 5.3 × 10^36 个可能的 v4 值。用生日问题的近似公式,可以算出要让"至少两个相同"的概率达到 50%,需要的 UUID 数量 n:

n ≈ √(2 · ln 2 · 2^122) ≈ 2.71 × 10^18

也就是约 271 亿亿个 UUID。即使每秒生成 10 亿个,也要大约 86 年才能达到这个数量。在现实的数量级下,风险可以忽略:

已生成的 v4 UUID 数量 出现任意碰撞的概率
10 亿(10^9) 约 9.4 × 10^-20
1 万亿(10^12) 约 9.4 × 10^-14
103 万亿(1.03 × 10^14) 约十亿分之一
2.71 × 10^18 约 50%

这些数字的前提是随机数生成器质量良好。实际中的碰撞通常来自程序错误:随机数生成器种子设置不当、克隆的虚拟机复用了同样的状态,或者代码复制了已有 ID 而不是生成新的。因此数据库中的唯一约束仍然值得保留。

UUID 与 GUID 的区别是什么?

实际上没有区别。GUID(Globally Unique Identifier,全局唯一标识符)是 Microsoft 对同一种 128 位值的称呼,用于 Windows、COM、.NET 和 SQL Server。例如 .NET 的 Guid.NewGuid() 生成的就是普通的版本 4 UUID。区别只在显示和存储方式上:

文本形式:        f47ac10b-58cc-4372-a567-0e02b2c3d479
RFC 顺序:        f4 7a c1 0b | 58 cc | 43 72 | a5 67 0e 02 b2 c3 d4 79
微软顺序:        0b c1 7a f4 | cc 58 | 72 43 | a5 67 0e 02 b2 c3 d4 79

文本完全相同,只是 16 个原始字节不同。如果在 Microsoft 系统和期望 RFC 字节序的系统之间直接复制二进制 GUID,值就会错乱。应通过文本形式转换,或者在 .NET 8 及以上版本中使用 ToByteArray(bigEndian: true)。Microsoft 在 Guid.ToByteArray 参考文档中说明了这些字节组的反转。

所以"UUID 还是 GUID"只是叫法问题,并不需要你做选择。

主键该用 UUID v4 还是 v7?

两者都是 128 位 UUID,但在索引中的表现差别很大。

v7 还能按 ID 排序得到创建顺序,并直接从 ID 中读出创建时间。这也是它的缺点:任何看到 v7 ID 的人都能知道记录的创建时间,精确到毫秒。对需要隐藏时间信息的公开标识符使用 v4,对写入量大的大表内部主键使用 v7。

如何高效存储 UUID

存储 16 个字节,而不是 36 个字符的文本。文本列每个值至少占用 36 个字节,是二进制的两倍多,而且每个包含该键的索引都会随之变大。

只在系统边界(如 API 和日志)才转换成文本。

如何在代码中生成 UUID

大多数语言都内置了生成器:

import uuid
uuid.uuid4()                                   # random v4
uuid.uuid7()                                   # v7, Python 3.14+
uuid.uuid5(uuid.NAMESPACE_DNS, "example.com")  # cfbff0d1-9375-5685-968c-48ce8b15ae17
crypto.randomUUID(); // v4, in browsers (HTTPS pages) and Node.js
SELECT gen_random_uuid();  -- v4, built in since PostgreSQL 13
SELECT uuidv7();           -- v7, PostgreSQL 18+
Guid.NewGuid();         // v4
Guid.CreateVersion7();  // v7, .NET 9+

crypto.randomUUID() 的说明见 MDN。在浏览器中,它只能在安全上下文(HTTPS 页面)中使用。

如何用正则表达式校验 UUID

下面的模式匹配版本 1–8、标准变体的规范格式(请使用不区分大小写的匹配):

^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$

[1-8] 检查版本位,[89ab] 检查变体位。如果还想接受 Nil 和 Max UUID、花括号或 urn:uuid: 前缀,需要另外添加检查。

UUID 不是秘密

UUID 用于标识,而不是保护。RFC 9562 指出,实现不应假定 UUID 难以猜测,也不得把 UUID 当作安全凭据使用。v1 会暴露创建时间,传统上还会暴露生成它的机器的 MAC 地址;v7 会暴露创建时间。即使是安全生成器产生的 v4,也不是为密码重置令牌或 API 密钥设计的。这类用途应使用专门的随机令牌,例如用 令牌生成器 生成,并且每次请求时仍要检查权限。

UUID 的替代方案

ULID 是一种目标相近的常见替代方案:同样是 128 位,包含 48 位毫秒时间戳和 80 个随机位,写成 26 个 Crockford Base32 字符,因此按文本排序即可得到时间顺序。如果你需要这种格式,ULID 生成器 可以生成、解码 ULID,并把它们转换成 UUID。对于新项目,UUID v7 提供同样的时间排序,同时保留数据库原生支持的标准 UUID 格式。

在线生成和检查 UUID

免费的 UUID 生成器 完全在浏览器中运行。它可以生成 v1、v3、v4、v5 和 v7 UUID 以及 Nil 和 Max 值,每次最多 500 个。你可以选择小写、大写或花括号格式,去掉连字符,用换行、逗号、空格或 JSON 数组分隔列表,然后复制或下载为 .txt 或 .json 文件。生成 v3 和 v5 时,可选择 DNS、URL、OID 或 X.500 命名空间,也可以粘贴自己的命名空间。

内置校验器接受规范格式、花括号、urn:uuid: 和不带连字符的输入,并显示版本、变体和规范形式。它能解码 v1 和 v7 UUID 中的时间戳,以及 v1 的时钟序列和节点。几点限制:它不生成 v6 和 v8;v1 使用随机节点而不是你的 MAC 地址;同一毫秒内生成的 v7 ID 不保证按创建顺序排序,因为时间戳之后的位是随机数,而不是计数器。

常见问题

UUID 和 GUID 是一回事吗?

是的。GUID 是 Microsoft 对 UUID 的称呼。值和文本格式都相同;Microsoft 工具常用大写加花括号显示 GUID,部分 Microsoft API 在二进制形式中以小端字节序存储前三个字段。

两个 UUID 会重复吗?

理论上会,实际上几乎不会。对于 v4,需要约 2.71 × 10^18 个 UUID,出现一次重复的概率才达到 50%。真正的重复通常来自软件缺陷或损坏的随机数生成器,所以仍应在键列上保留唯一约束。

应该用 UUID v4 还是 v7?

插入频繁的表的主键用 v7,因为按时间排序的 ID 能让索引保持紧凑,并按创建时间排序。如果 ID 会公开,且不应透露记录的创建时间,就用 v4。

UUID 有多长?

UUID 是 128 位,即 16 个字节。标准文本形式为 36 个字符:32 个十六进制数字加 4 个连字符。去掉连字符是 32 个字符,加上花括号是 38 个。

在 URL 中使用 UUID 安全吗?

可以公开显示,但它不能代替访问控制。随机 v4 很难猜,但可能通过日志、浏览器历史记录或 Referer 请求头泄露,而 v1 和 v7 会暴露创建时间。务必检查用户是否有权访问该资源。

免费试用:UUID 生成器 免费使用,无需注册账号。