反馈

UUID/GUID 深度解析:版本、结构与生成算法

UUID(Universally Unique Identifier,通用唯一标识符)是一个 128 位的数字,通常写成 32 个十六进制字符加 4 个连字符,比如 550e8400-e29b-41d4-a716-446655440000。它的设计目标很直接:不需要任何中央协调机构(不用查数据库、不用连服务器),任意两台机器各自生成的 UUID 几乎不可能撞上


目录

  1. 为什么 128 位几乎不会重复
  2. 标准结构:8-4-4-4-12
  3. 版本对比:v1 到 v7
  4. GUID 和 UUID 是一回事吗
  5. 用 UUID 做数据库主键:优缺点
  6. 代码示例

1. 为什么 128 位几乎不会重复

128 位能表示 2¹²⁸ ≈ 3.4×10³⁸ 个不同的值。以最常用的 v4(随机版本)为例,即使你每秒生成 10 亿个 UUID,连续生成 100 年,出现一次重复的概率也远低于"地球被小行星撞击"的概率——这就是"几乎不可能重复"背后的数学依据,不是一句空话。

2. 标准结构:8-4-4-4-12

550e8400-e29b-41d4-a716-446655440000
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx

36 个字符里,32 个是十六进制数字,4 个是分隔用的连字符。其中两个位置有特殊含义:

  • 第三段第一位(M):版本号,标识这是 v1~v7 中的哪个版本
  • 第四段第一位(N):变体(variant),标识 UUID 遵循的规范(几乎所有现代 UUID 都是 8/9/a/b 开头,表示 RFC 4122 变体)

拿到一个 UUID,看第三段开头就能知道它是哪个版本生成的。

3. 版本对比:v1 到 v7

版本 生成依据 特点 典型场景
v1 时间戳 + 网卡 MAC 地址 可能暴露生成机器的 MAC 地址,有隐私隐患 早期分布式系统
v3 命名空间 + 名称,MD5 哈希 相同输入永远得到相同 UUID(确定性) 需要"同名必同码"的场景
v4 纯随机数 最常用,无隐私泄露风险 绝大多数通用场景
v5 命名空间 + 名称,SHA-1 哈希 和 v3 类似但用更安全的哈希算法 替代 v3
v7 时间戳(毫秒级)+ 随机数 前缀按时间排序,兼顾唯一性和索引效率 数据库主键(新标准,2024 年纳入 RFC 9562)

v4 是目前最广泛使用的版本,因为它不依赖任何机器信息、生成简单。v7 是最新加入标准的版本,专门为了解决"UUID 做数据库主键会导致索引碎片化"这个长期痛点而设计。

4. GUID 和 UUID 是一回事吗

是的。GUID(Globally Unique Identifier)是微软的叫法,UUID 是 RFC 标准里的名称,两者指的是同一套东西,格式完全一致,只是叫法不同——你在 .NET/Windows 生态里看到 GUID,在其它地方看到 UUID,不用纠结区别。

5. 用 UUID 做数据库主键:优缺点

优点

  • 客户端可以在插入前就生成好 ID,不用等数据库返回自增值
  • 分布式系统里多个节点各自生成,不会冲突,不需要协调
  • 不会暴露"总共有多少条记录"这类信息(自增 ID 容易被猜到)

缺点

  • 用 v1/v4 这类"完全随机"的版本做主键,会导致 B+ 树索引频繁分裂重排(新插入的值不是递增的,到处插空),写入性能和存储空间都比自增 ID 差
  • 128 位比 64 位自增 ID 占用更多存储空间和索引空间

折中方案:如果一定要用 UUID 做主键,优先选 v7——它的前缀是时间戳,本质上是"近似递增"的,能大幅缓解索引碎片化问题,同时保留了 UUID 无需协调生成的优点。

6. 代码示例

// 现代浏览器和 Node.js 都内置了 v4 生成
const id = crypto.randomUUID();
console.log(id); // 例如 "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
import uuid
print(uuid.uuid4())

在线 UUID/GUID 生成工具:UUID生成