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 的模式:
在 UUID v4 中,128 位中的 122 位是随机的。其余 6 位是规范要求的固定字段:4 位编码版本(0100 = 4),2 位编码 RFC 4122 变体(10)。这些固定位就是为什么第三组始终以 4 开头,第四组始终以 8、9、a 或 b 开头的原因。
UUID v4 的结构
解析 550e8400-e29b-41d4-a716-446655440000:
| 段 | 位数 | 含义 |
|---|---|---|
| 550e8400 | 32 位随机 | time_low(名称为历史遗留——在 v4 中完全随机) |
| e29b | 16 位随机 | time_mid(历史遗留名称——在 v4 中完全随机) |
| 41d4 | 4 位固定 + 12 位随机 | 版本半字节 4(二进制 0100)+ 12 位随机 |
| a716 | 2 位固定 + 14 位随机 | 变体位 10(第一字节的高位)+ 14 位随机 |
| 446655440000 | 48 位随机 | node(在 v4 中完全随机) |
8、9、a 或 b 之一——因为该字节的高两位固定为 10(RFC 4122 变体标记),剩余两位可自由变化。UUID v4 与其他版本的对比
RFC 4122 定义了五个 UUID 版本,每个版本解决不同的问题:
将 60 位时间戳(自 1582 年 10 月起的 100 纳秒间隔)与主机 MAC 地址组合。在单机上单调递增。
Use when: 你需要有时间顺序的 ID 且不介意泄露服务器身份和生成时间。
确定性的:相同的命名空间 + 名称始终产生相同的 UUID。使用 MD5 哈希。
Use when: 你需要从已知命名空间(如 DNS 名称)生成可复现的 ID。推荐使用 v5 而非 v3。
122 位加密安全随机数。没有时间戳、没有 MAC、没有命名空间。最常用的通用选择。
Use when: 你需要没有结构含义且隐私性最强的唯一 ID。
类似 v3 但使用 SHA-1。仍然从命名空间 + 名称确定性生成。
Use when: 你需要可复现的、基于内容寻址的标识符(例如 URL 标识的资源的稳定 ID)。
更新版本(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 附加到每个日志行和分布式追踪跨度。不需要跨服务或机器协调。
碰撞概率
有 122 个随机位,UUID v4 空间包含 2122 ≈ 5.3 × 1036 个可能的值。碰撞概率遵循生日问题:
常被引用的基准:要有 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+ 中原生可用。无需安装任何包。
// 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 包)
const { v4: uuidv4 } = require('uuid')
const id = uuidv4()
// → "110e8400-e29b-41d4-a716-446655440000"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
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
# Cargo.toml
[dependencies]
uuid = { version = "1", features = ["v4"] }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 存储为字符串还是二进制?
对于大多数数据库,存储为 UUID 或 BINARY(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 解析器接受两种形式。如有疑问,使用规范的连字符形式以获得与第三方工具和数据库的最大兼容性。
const id = crypto.randomUUID() // "550e8400-e29b-41d4-a716-446655440000"
const compact = id.replaceAll('-', '') // "550e8400e29b41d4a716446655440000"