UUID v4生成器

Generate cryptographically random UUID v4

格式化

数量:

UUID v4 是现代软件中部署最广泛的 UUID 版本。与从时间戳或命名空间哈希中提取比特的其他版本不同,UUID v4 完全由随机数据构建——使其成为需要不携带任何来源元数据的唯一标识符时最简单、最通用的选择。

此生成器使用 crypto.randomUUID(),这是原生浏览器和 Node.js API,从操作系统的加密安全随机数生成器中获取熵——与 TLS 密钥材料使用的来源相同。

什么是 UUID v4?

通用唯一标识符(UUID)是在 RFC 4122 中标准化的 128 位标签。它通常表示为 32 个十六进制数字,以连字符分组为 8-4-4-4-12 的模式:

550e8400-e29b-41d4-a716-446655440000

在 UUID v4 中,128 位中的 122 位是随机的。其余 6 位是规范要求的固定字段:4 位编码版本(0100 = 4),2 位编码 RFC 4122 变体(10)。这些固定位就是为什么第三组始终以 4 开头,第四组始终以 89ab 开头的原因。

UUID v4 的结构

解析 550e8400-e29b-41d4-a716-446655440000

位数含义
550e840032 位随机time_low(名称为历史遗留——在 v4 中完全随机)
e29b16 位随机time_mid(历史遗留名称——在 v4 中完全随机)
41d44 位固定 + 12 位随机版本半字节 4(二进制 0100)+ 12 位随机
a7162 位固定 + 14 位随机变体位 10(第一字节的高位)+ 14 位随机
44665544000048 位随机node(在 v4 中完全随机)
Note:第四组开头的变体半字节始终是 89ab 之一——因为该字节的高两位固定为 10(RFC 4122 变体标记),剩余两位可自由变化。

UUID v4 与其他版本的对比

RFC 4122 定义了五个 UUID 版本,每个版本解决不同的问题:

UUID v1时间戳 + MAC

将 60 位时间戳(自 1582 年 10 月起的 100 纳秒间隔)与主机 MAC 地址组合。在单机上单调递增。

Use when: 你需要有时间顺序的 ID 且不介意泄露服务器身份和生成时间。

UUID v3MD5 哈希

确定性的:相同的命名空间 + 名称始终产生相同的 UUID。使用 MD5 哈希。

Use when: 你需要从已知命名空间(如 DNS 名称)生成可复现的 ID。推荐使用 v5 而非 v3。

UUID v4随机

122 位加密安全随机数。没有时间戳、没有 MAC、没有命名空间。最常用的通用选择。

Use when: 你需要没有结构含义且隐私性最强的唯一 ID。

UUID v5SHA-1 哈希

类似 v3 但使用 SHA-1。仍然从命名空间 + 名称确定性生成。

Use when: 你需要可复现的、基于内容寻址的标识符(例如 URL 标识的资源的稳定 ID)。

UUID v7按时间排序的随机

更新版本(RFC 9562,2024 年)。在高位编码 Unix 毫秒时间戳,其余为随机位。可排序且对数据库友好。

Use when: 你需要具有自然时间排序的数据库索引友好型 ID(新项目中优先选择 v1)。

何时使用 UUID v4

在绝大多数只需要「唯一 ID」而没有额外约束的情况下,UUID v4 是正确的选择:

用户和账户 ID

不透明的用户 ID,不会泄露账户创建时间或服务器身份。无法被枚举或猜测。

数据库主键

适用于任何数据库引擎。UUID v4 可以安全地在客户端生成并从分布式来源合并,无需协调——不需要序列表或中央 ID 服务。

会话和令牌 ID

122 位随机性使暴力猜测在计算上不可行——强度与 122 位随机令牌相当。

文件和对象名称

用于上传的去重安全文件名、S3 对象键或缓存条目。无需担心两个客户端写入同一键。

幂等性密钥

在提交请求前在客户端生成 UUID。服务器可以安全地去重重试请求,无需共享计数器。

关联和追踪 ID

将 UUID 附加到每个日志行和分布式追踪跨度。不需要跨服务或机器协调。

Note:如果你的用例需要可排序的 ID(例如希望数据库行按插入时间聚集),请考虑改用 UUID v7。UUID v4 是故意随机的,在高插入速率下会导致 B 树索引碎片化。

碰撞概率

有 122 个随机位,UUID v4 空间包含 2122 ≈ 5.3 × 1036 个可能的值。碰撞概率遵循生日问题

生成的 UUID 数量碰撞概率
10 亿(109约 1 / 5.3 × 1018
1 万亿(1012约 1 / 5.3 × 1012
1018(1 艾字节级别)约 1 / 5,300

常被引用的基准:要有 50% 的概率产生单次碰撞,需要生成大约 2.71 × 1018 个 UUID。以每秒 10 亿个 UUID 的速率,这将需要大约 85 年的持续生成。对于任何实际应用,碰撞不是实际问题。

代码示例

JavaScript——浏览器和 Node.js 14.17+

crypto.randomUUID() 方法在所有现代浏览器(Chrome 92+、Firefox 95+、Safari 15.4+)和 Node.js 14.17+ 中原生可用。无需安装任何包。

js
// Browser or Node.js 14.17+
const id = crypto.randomUUID()
// → "110e8400-e29b-41d4-a716-446655440000"

// Generate multiple
const ids = Array.from({ length: 5 }, () => crypto.randomUUID())

Node.js——旧版本(uuid 包)

js
const { v4: uuidv4 } = require('uuid')

const id = uuidv4()
// → "110e8400-e29b-41d4-a716-446655440000"

Python

python
import uuid

# Generate a UUID v4
id = str(uuid.uuid4())
# → '110e8400-e29b-41d4-a716-446655440000'

# The uuid module uses os.urandom() — cryptographically secure
print(uuid.uuid4().hex)  # without hyphens
# → '110e8400e29b41d4a716446655440000'

Go

go
import "github.com/google/uuid"

id := uuid.New().String()
// → "110e8400-e29b-41d4-a716-446655440000"

// Or using the standard library (Go 1.20+ with math/rand/v2 is NOT cryptographic)
// Always prefer github.com/google/uuid for production use

Rust

toml
# Cargo.toml
[dependencies]
uuid = { version = "1", features = ["v4"] }
rust
use uuid::Uuid;

let id = Uuid::new_v4().to_string();
// → "110e8400-e29b-41d4-a716-446655440000"

常见问题

UUID v4 是加密安全的吗?

UUID v4 本身不是安全原语——它是一种标识符格式。但是,当通过 crypto.randomUUID()(浏览器或 Node.js)或同等的操作系统级 API 生成时,底层熵是加密安全的。这意味着 UUID v4 值适合用作会话令牌或幂等性密钥,在这些场景中不可预测性很重要。不要在安全敏感的上下文中使用基于 Math.random() 的 UUID 生成器——只使用明确从操作系统 CSPRNG 获取熵的 API。

两个 UUID v4 有可能相等吗?

理论上是的,但实际上不会。在任何现实数据集(数十亿个 ID)中产生重复的概率极其微小——比硬件故障导致数据损坏的可能性小得多。UUID v4 碰撞在生产系统设计中被视为不可能发生的事情。如果你确实需要零碰撞保证,请改用中央计数器或数据库序列。

UUID v4 vs nanoid——我应该用哪个?

两者都是由 CSPRNG 支持的随机 ID 生成器。主要区别:

  • UUID v4 遵循 RFC 4122 标准,被每个数据库和框架识别,且不需要依赖(原生 crypto.randomUUID())。
  • nanoid 使用 URL 安全字母表,默认更短(21 个字符 vs 36 个字符)。当 URL 长度或可读性很重要时很有用。需要 npm 包。

当与外部系统的互操作性很重要时(API、数据库、日志基础设施),优先选择 UUID v4。当你想要更短的 ID 且控制整个技术栈时,优先选择 nanoid。

我应该在数据库中将 UUID 存储为字符串还是二进制?

对于大多数数据库,存储为 UUIDBINARY(16) 列(16 字节)比 VARCHAR(36) 字符串(36 字节)更高效。PostgreSQL 有原生的 uuid 类型。MySQL 和 MariaDB 可以很好地配合 BINARY(16)UUID_TO_BIN() / BIN_TO_UUID() 辅助函数使用。SQLite 用户通常存储为 TEXT。存储选择对唯一性或正确性没有影响。

为什么 UUID v4 有连字符——我可以省略它们吗?

连字符是 RFC 4122 定义的规范 UUID 表示的一部分。它们纯粹是装饰性的——不携带任何信息,不影响 128 位值。省略它们会得到一个功能等效的紧凑 32 字符十六进制字符串。大多数 UUID 解析器接受两种形式。如有疑问,使用规范的连字符形式以获得与第三方工具和数据库的最大兼容性。

js
const id = crypto.randomUUID()              // "550e8400-e29b-41d4-a716-446655440000"
const compact = id.replaceAll('-', '')     // "550e8400e29b41d4a716446655440000"