UUID 是什么?为什么开发者都在用?

UUIDUniversally Unique Identifier,通用唯一标识符)是一种 128 位(16 字节)的标识符,由 RFC 4122 定义(2024 年扩展为 RFC 9562)。在分布式系统、数据库主键、订单号、文件名等场景中,UUID 几乎成了开发者的默认选择。理解 UUID 的版本差异、碰撞概率与性能影响,是后端和全栈工程师的必修课。

UUID 格式与长度

UUID 用 32 个十六进制字符表示,按 8-4-4-4-12 的规则分成 5 段,用 4 个连字符连接,总长度 36 个字符。一个经典 v4 UUID 长这样:

550e8400-e29b-41d4-a716-446655440000
│        │    │ │  │           │
8位      4位  4位 4位        12位
└─ 32 hex + 4 hyphens = 36 chars ─┘

其中第 13 位(版本位)标识 UUID 版本,第 17 位(variant 位)固定为 8/9/A/B 之一。例如上面这个 v4 UUID,第 13 位是 4,第 17 位是 a(属于 10xx 变体)。

UUID 各版本对比

从 1990 年代的 v1,到 2024 年新出的 v7,每个版本针对不同场景设计:

v1 — 时间戳 + MAC 地址

前 60 位是时间戳(100ns 精度),后 48 位是网卡 MAC 地址。优势:天然有序,可反推出生成时间与机器。缺点:会暴露 MAC 地址,可被追踪,隐私敏感场景不推荐。

v3 — MD5 哈希(基于命名空间+名字)

对「命名空间 UUID + 名字」做 MD5 哈希。同一个名字在同一命名空间下永远生成相同 UUID,适合需要确定性 ID 的场景(如根据 URL 生成固定 ID)。

v4 — 纯随机(最常用)

除版本位和 variant 位外,122 位全部由密码学安全随机数生成。完全无序、无法预测、零协调成本。当下 90% 的项目都默认用 v4

v5 — SHA-1 哈希(v3 替代)

和 v3 结构相同,但用 SHA-1 替代 MD5,碰撞抗性更强。Python 的 uuid.uuid5()、Node 的 uuidv5 库都支持。

v7 — 时间排序 + 随机(2024 新标准)

RFC 9562(2024-05 发布)引入的新版本。前 48 位是毫秒 Unix 时间戳,剩余位随机。既能排序又保持随机性,是数据库主键的最佳选择,正在快速取代 v4。

UUID vs 自增 ID:何时用哪个

两种主键方案各有适用场景:

UUID 的优势:无需中心化分配,可离线生成;天然安全(无法被遍历猜到下一个 ID);合并多数据源时不冲突;适合分布式系统、微服务、前后端分离架构。

自增 ID 的优势:存储紧凑(8 字节 vs 16 字节)、索引占用小、写入性能高、单调递增避免 B+ 树频繁分裂;适合单库、读多写少、不暴露业务量级的内部系统。

实际选型建议:MySQL/PostgreSQL 内部主键可用 BIGINT,公开标识符用 UUID;新项目优先考虑 UUID v7,兼顾有序与唯一。

UUID 实战场景

1. 数据库主键

MySQL 用 CHAR(36) BINARYBINARY(16) 存储;PostgreSQL 原生支持 uuid 类型。配合 v7 还能让 B-Tree 索引的写入接近自增 ID 的效率。

2. 订单号 / 交易流水号

电商订单、支付流水用 UUID v4 可避免「下一个订单号是多少」被猜到造成的安全问题。Stripe、Shopify 等大厂订单系统底层都用类似方案。

3. 文件名去重

用户上传头像到对象存储(S3、OSS),用 UUID 重命名 avatar-550e8400-e29b-41d4.jpg,彻底杜绝同名覆盖。

4. 分布式系统与消息追踪

微服务链路追踪的 traceId、消息队列的 messageId、API 网关的 requestId,几乎都默认用 UUID。配合 ELK、Loki 等日志系统,能把一个请求在几十个服务间的完整路径串起来。

碰撞概率有多低?

这是大家最关心的问题。UUID v4 有 122 位随机空间(2¹²² ≈ 5.3×10³⁶)。按「生日悖论」公式估算:即使每秒生成 10 亿个 UUID,连续生成 100 年(约 3.15×10¹⁸ 个),碰撞概率也仅约 10⁻¹²——也就是说,发生碰撞的概率是一万亿分之一。

实际工程中,v4 碰撞的概率远低于硬盘损坏、机房断电等事故。v7 因为前 48 位是时间戳,碰撞空间略小(2⁷⁴),但同样安全。

如何用 DevToolbox 一键生成 UUID

无需安装任何软件,浏览器打开即用:

步骤 1:访问 https://devstoolbox.net/tools/uuid-generator.html

步骤 2:选择版本(v1 / v4 / v7)和生成数量(1–500 个)

步骤 3:点击「生成」,支持一键复制全部、导出为 JSON / TXT

步骤 4:所有 UUID 都在浏览器本地生成,不会上传到服务器

底层使用 Web Crypto API 的 crypto.getRandomValues(),与 Node.js 的 crypto.randomUUID()(14.17+)属于同一安全等级。

常见问题

Q1:UUID 会被用完吗?

不会。v4 有 5.3×10³⁶ 种可能,宇宙中所有星星的原子加起来也不到这个数量级。即使全球每秒钟生成 10 亿个 UUID,耗尽全部空间需要 10 万亿年。短期内,UUID 是数学意义上「用不完」的

Q2:v4 和 v7 选哪个?

如果是 数据库主键、消息 ID 等需要排序或索引的场景,优先选 v7(2024 标准,PostgreSQL 17+、SQLite 3.46+ 原生支持)。如果是 会话 token、文件名、一次性 ID等无需排序的场景,v4 仍然够用且生态最成熟。

Q3:UUID 当主键,数据库性能会变差吗?

会,但可控。UUID 是 16 字节,比 BIGINT(8 字节)大;无序的 v4 会让 B+ 树频繁页分裂,写入性能可能下降 10%–30%。三个常用优化方案:① 用 BINARY(16) 存储而非 CHAR(36);② 主键选 v7 保持有序;③ UUID 只做业务主键,聚簇索引仍用自增 ID。

Q4:UUID 安全吗?能不能被猜到?

crypto.randomUUID() 或基于 crypto.getRandomValues() 生成的 v4/v7 UUID 是密码学安全的,无法预测。注意避开基于时间戳+计数器的自造方案,那种「类 UUID」可能被枚举攻击。

结论

UUID 是分布式时代的「身份证」——128 位足够大、碰撞概率足够低、跨系统足够通用。新项目建议直接用 UUID v7,老项目迁移到 v4 也完全够用。下次设计主键时,别再用 timestamp + random() 拼凑了,让标准来替你兜底。

立即生成 UUID → https://devstoolbox.net/tools/uuid-generator.html

相关文章

如何格式化 JSON:完整指南

Base64 编码解码完全指南