UUID(通用唯一标识符)是分布式系统、数据库和 API 中生成唯一 ID 的标准方法。无需中央协调;随机生成的 v4 UUID 重复的概率小到在实践中可以忽略。
UUID 是什么?
UUID 是一个 128 位的数字,通常表示为 5 组十六进制数字,用连字符分隔:
550e8400-e29b-41d4-a716-446655440000
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
M:版本号(1–8;RFC 9562 新增了 6、7、8)N:变体(8、9、a 或 b)
标准格式是 8-4-4-4-12,共 36 个字符(含连字符),32 个十六进制字符。
UUID 版本
| 版本 | 生成方式 | 适用场景 |
|---|---|---|
| v1 | 时间戳 + MAC 地址 | 需要时间排序但可能泄露 MAC 地址 |
| v3 | 命名空间 + 名称的 MD5 | 确定性 ID,相同输入产生相同 UUID |
| v4 | 随机 | 最常用——纯随机,无信息泄露 |
| v5 | 命名空间 + 名称的 SHA-1 | 确定性 ID;RFC 9562 建议优先用 v5 而非 v3 |
v4 是绝大多数场景的正确选择。
UUID v4 碰撞概率
每秒生成 10 亿个 UUID,需要约 86 年才会有 50% 的概率出现一次碰撞。实践中,正确生成的 v4 UUID 之间的碰撞可以忽略。
在线生成 UUID
- 单个或批量生成
- 一键复制
- UUID 在浏览器内生成,不发送到服务器
在代码中生成 UUID
JavaScript(Node.js 18+)
import { randomUUID } from 'crypto';
const id = randomUUID();
// 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
Node.js 14.17+ 也可用:crypto.randomUUID()
JavaScript(浏览器)
const id = crypto.randomUUID();
// 所有现代浏览器均支持(Chrome 92+, Firefox 95+, Safari 15.4+)
使用 uuid 库(兼容旧版本)
npm install uuid
import { v4 as uuidv4 } from 'uuid';
const id = uuidv4();
Python
import uuid
# v4(随机)
id = uuid.uuid4()
print(str(id)) # 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
# v5(命名空间,确定性)
id = uuid.uuid5(uuid.NAMESPACE_URL, 'https://zerotool.dev')
Go
import "github.com/google/uuid"
id := uuid.New()
fmt.Println(id.String())
SQL(PostgreSQL)
-- 生成 UUID
SELECT gen_random_uuid();
-- 用 UUID 作为主键
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL
);
UUID 作为数据库主键
优点
- 全局唯一 — 多服务、多数据库之间不会冲突
- 无需中央序列 — 客户端可提前生成 ID
- 不泄露信息 — 不像自增 ID 会暴露记录数量
缺点
- 索引性能 — 随机 UUID 导致 B-tree 索引碎片化,插入性能比自增整数差
- 体积 — 16 字节 vs 整数的 4-8 字节
- 不可排序 — v4 UUID 无时间顺序
解决方案:UUID v7
UUID v7 将时间戳放在高位,兼顾唯一性和单调递增,是数据库主键的理想选择。目前部分库已支持:
// Node.js
import { v7 as uuidv7 } from 'uuid';
const id = uuidv7();
// '017f22e2-79b0-7cc3-98c4-dc0c0c07398f'
// 前面部分是毫秒级时间戳,天然有序
格式变体
标准: 550e8400-e29b-41d4-a716-446655440000
无连字符:550e8400e29b41d4a716446655440000
大写: 550E8400-E29B-41D4-A716-446655440000
URN: urn:uuid:550e8400-e29b-41d4-a716-446655440000
存储到数据库时,优先使用 16 字节的二进制形式而非 VARCHAR:PostgreSQL 用原生 uuid 类型;MySQL 8.0 没有原生 UUID 类型,用 BINARY(16) 配合 UUID_TO_BIN()。可节省空间并加快比较速度。
验证 UUID
// JavaScript
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
UUID_REGEX.test('550e8400-e29b-41d4-a716-446655440000'); // true
# Python
import uuid
def is_valid_uuid(val):
try:
uuid.UUID(str(val))
return True
except ValueError:
return False
总结
| 需求 | 推荐方案 |
|---|---|
| 快速生成 | ZeroTool UUID 生成器 |
| 浏览器/Node.js | crypto.randomUUID() |
| Python | uuid.uuid4() |
| 数据库主键(有序) | UUID v7 或 ULID |
| 确定性 ID | UUID v5 |
UUID v4 适合绝大多数场景。如果需要数据库友好的有序 ID,考虑 UUID v7 或 ULID。