UUID 生成器:v4/v5 批量生成
数据库主键、API 请求 ID、文件名唯一化、分布式系统节点标识——到处需要唯一标识符。UUID(Universally Unique Identifier)是业界标准。本文详解 UUID 的版本差异、生成方法、批量使用。
什么是 UUID?
UUID 是 128 位的标识符,标准格式:
123e4567-e89b-12d3-a456-426614174000
- 32 个十六进制字符 + 4 个连字符
- 共 36 字符
- 形如 8-4-4-4-12
容量
UUID 总共 2^128 ≈ 3.4 × 10^38 种可能。如果每秒生成 10 亿个 UUID,连续生成 85 年才有 50% 概率出现重复。
唯一性来源
不同 UUID 版本的唯一性保证方式不同:
- v1:基于时间和网卡 MAC 地址
- v3:基于命名空间和名字的 MD5
- v4:随机
- v5:基于命名空间和名字的 SHA-1
- v6、v7、v8:新版本,时间有序
UUID 各版本详解
v1:时间 + MAC
格式:时间戳 - 版本(1) - 时钟序列 - MAC地址
例:a0eebc99-9c0b-11ea-bb37-0242ac130002
特点:
- 基于当前时间(100 纳秒精度)和机器 MAC
- 同一机器生成的 UUID 时间有序
- 暴露 MAC 地址(隐私问题)
- 适合:需要时间排序、单机生成
v3:命名空间 + 名字(MD5)
格式:基于 v3 算法,对 (命名空间UUID + 名字) 做 MD5
特点:
- 同一命名空间+名字 → 同一 UUID
- 适合:从名字生成确定性 ID
例:
命名空间:6ba7b810-9dad-11d1-80b4-00c04fd430c8 (DNS)
名字:example.com
v3 UUID:9073926b-929d-31ec-b3cf-712c1a9c5c9b
v4:随机
格式:随机 122 位 + 版本(4) + 变体
例:f47ac10b-58cc-4372-a567-0e02b2c3d479
特点:
- 完全随机
- 不依赖机器、时间
- 99.99% 使用场景都用 v4
- 适合:通用场景
v5:命名空间 + 名字(SHA-1)
与 v3 类似,但用 SHA-1 代替 MD5。
例:
命名空间:6ba7b810-9dad-11d1-80b4-00c04fd430c8 (DNS)
名字:example.com
v5 UUID:cfbff0d1-9375-5685-968c-48ce8b15ae57
特点:
- 同一命名空间+名字 → 同一 UUID
- 比 v3 更安全(SHA-1 比 MD5 强)
- 适合:需要确定性 ID 的场景
v6/v7/v8(新版本)
- v6:时间在前,便于排序
- v7:Unix 时间戳 + 随机
- v8:自定义
目前主流仍是 v4,新版本逐渐推广。
52tool UUID 生成器
工具地址:UUID 生成器
功能
- v1 / v4 / v5 三种版本
- 批量生成(1-1000 个)
- 一键复制
- 大写/小写切换
- 带连字符 / 不带连字符
- 浏览器端生成,不联网
实战 1:批量生成 v4
输入:
版本:v4
数量:10
格式:小写带连字符
输出:
4d23ba39-1d8f-4d3a-b9c2-7e8f1a2b3c4d
7a8b9c1d-2e3f-4a5b-8c7d-9e0f1a2b3c4d
...
实战 2:v5 确定性生成
输入:
版本:v5
命名空间:6ba7b810-9dad-11d1-80b4-00c04fd430c8 (DNS)
名字:www.example.com
输出:
cfbff0d1-9375-5685-968c-48ce8b15ae57
同一输入永远生成同一 UUID,适合做"哈希型唯一 ID"。
实战 3:自定义格式
需要不带连字符的 UUID(如某些旧系统):
版本:v4
格式:小写不带连字符
输出:
4d23ba391d8f4d3ab9c27e8f1a2b3c4d
标准命名空间 UUID
v3/v5 需要命名空间 UUID,标准定义了 4 个:
| 命名空间 | UUID | 用途 |
| DNS | 6ba7b810-9dad-11d1-80b4-00c04fd430c8 | 域名 |
| URL | 6ba7b811-9dad-11d1-80b4-00c04fd430c8 | URL |
| OID | 6ba7b812-9dad-11d1-80b4-00c04fd430c8 | ISO OID |
| X.500 | 6ba7b814-9dad-11d1-80b4-00c04fd430c8 | X.500 DN |
也可自定义命名空间 UUID。
实战场景
场景 1:数据库主键
不用自增 ID(1, 2, 3...),改用 UUID:
CREATE TABLE users (
id CHAR(36) PRIMARY KEY,
name VARCHAR(100)
);
INSERT INTO users (id, name) VALUES ('4d23ba39-...', '张三');
优势:
- 分布式生成不冲突
- 不暴露业务量(看不到注册到第几个用户)
- 合并数据库不冲突
劣势:
- 占用 36 字节 vs 4 字节(INT)
- 索引性能略差
- 不可读
场景 2:API 请求 ID
每次 API 请求生成 UUID 作为 Request-ID:
POST /api/orders HTTP/1.1
X-Request-ID: 4d23ba39-1d8f-4d3a-b9c2-7e8f1a2b3c4d
HTTP/1.1 200 OK
X-Request-ID: 4d23ba39-1d8f-4d3a-b9c2-7e8f1a2b3c4d
便于追踪日志、调试问题。
场景 3:文件名唯一化
用户上传头像,避免重名覆盖:
原始:avatar.png
新名:4d23ba39-1d8f-4d3a-b9c2-7e8f1a2b3c4d.png
场景 4:测试数据
生成 1000 个测试用户:
用 [52tool UUID 生成器](/tools/devtool/uuid) 批量生成 1000 个
导入数据库作为测试 ID
场景 5:分布式任务 ID
分布式任务队列(如 Celery),每个任务用 UUID 标识:
import uuid
task_id = str(uuid.uuid4())
queue.enqueue(task_id=task_id, ...)
跨节点不会冲突。
场景 6:客户端 ID(v5)
电商网站给未登录用户分配购物车 ID:
// 用域名作命名空间,浏览器指纹作名字
const namespace = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'; // URL
const name = navigator.userAgent + screen.width;
const cartId = uuidv5(name, namespace);
同一浏览器永远得到同一 ID(理论上)。
编程实现
JavaScript
// 原生不支持,需用库
// npm install uuid
import { v4, v5 } from 'uuid';
v4(); // '4d23ba39-...'
v5('example.com', '6ba7b810-9dad-11d1-80b4-00c04fd430c8');
或用浏览器原生 crypto.randomUUID()(支持 v4):
crypto.randomUUID(); // '4d23ba39-...'
Python
import uuid
# v4
uuid.uuid4() # UUID('4d23ba39-...')
# v5
uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com')
# UUID('cfbff0d1-9375-5685-968c-48ce8b15ae57')
# v1
uuid.uuid1() # 基于时间
Java
import java.util.UUID;
// v4
UUID id = UUID.randomUUID();
System.out.println(id); // 4d23ba39-...
// v3
UUID namespace = UUID.fromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8");
UUID id3 = UUID.nameUUIDFromBytes(...);
Go
import "github.com/google/uuid"
uuid.New() // v4
uuid.NewSHA1(namespace, []byte("example.com")) // v5
SQL
MySQL 8+:
SELECT UUID();
PostgreSQL:
-- 需要安装 uuid-ossp 扩展
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
SELECT uuid_generate_v4();
SELECT uuid_generate_v5(uuid_nil(), 'example.com');
Bash
uuidgen # Linux
uuidgen | tr 'A-Z' 'a-z' # 转小写
UUID 与其他唯一标识
UUID vs 自增 ID
| 维度 | UUID | 自增 ID |
| 长度 | 36 字节 | 4-8 字节 |
| 分布式 | 友好 | 不友好 |
| 可读 | 不可读 | 易读 |
| 安全 | 不暴露业务量 | 暴露用户数 |
| 索引 | 略慢 | 快 |
| 合并库 | 不冲突 | 冲突 |
UUID vs Snowflake(雪花算法)
Snowflake:64 位整数 ID,时间+机器+序列号
| 维度 | UUID | Snowflake |
| 长度 | 36 字节 | 8 字节 |
| 有序 | v1/v6/v7 排序,v4 随机 | 时间有序 |
| 依赖 | 无 | 需要协调机器 ID |
| 范围 | 2^128 | 2^63 |
UUID vs NanoID
NanoID:22 字符,更短,URL 安全
NanoID: V1StGXR8_Z5jdHi6B-myT
UUID: 4d23ba39-1d8f-4d3a-b9c2-7e8f1a2b3c4d
URL 友好场景选 NanoID,标准化场景选 UUID。
进阶技巧
技巧 1:用 v7 实现有序 UUID
v7 UUID 时间有序,适合做数据库主键(B+树索引性能更好):
017b1d6d-5f0f-7000-9c2d-7e8f1a2b3c4d
^ 7 = v7
时间戳在前,按时间排序。
技巧 2:缩短 UUID
去掉连字符节省 4 字节:
原:4d23ba39-1d8f-4d3a-b9c2-7e8f1a2b3c4d
缩:4d23ba391d8f4d3ab9c27e8f1a2b3c4d
或转 Base62:
原(36 字符):4d23ba39-1d8f-4d3a-b9c2-7e8f1a2b3c4d
Base62(22 字符):4wTRFPm9YwKfEaJHgTLPfN
技巧 3:UUID 作缓存键
const cacheKey = `user:${userId}:session:${uuidv4()}`;
每次会话独立 UUID,避免冲突。
技巧 4:批量预生成
# 生成 10000 个 UUID 存文件
for i in {1..10000}; do uuidgen; done > uuids.txt
需要时取一个用。
常见问题解答
Q: UUID 真的不会重复吗?
A: v4 重复概率极低。生成 103 万亿个 UUID 才有 50% 概率出现一次重复。日常使用可视为不重复。但随机数源质量差(如 Math.random())可能导致重复,建议用密码学安全的随机源。
Q: UUID 可以反推回时间或机器吗?
A: v1 可以——它包含时间戳和 MAC。v4 不行——完全随机。v3/v5 也不行——是哈希值。
Q: UUID 字母大写还是小写?
A: 标准是大小写不敏感。但实际使用中常小写。数据库存储建议统一小写,避免大小写导致的查询问题。52tool 生成器支持大小写切换。
Q: UUID 作数据库主键性能差吗?
A: 比 INT 自增慢约 10-20%,但绝对值仍很快(毫秒级)。v4 随机导致 B+树索引碎片化,v7 时间有序更友好。如果不是超高并发,UUID 性能足够。
Q: UUID 能用 MD5/SHA 替代吗?
A: 不能。MD5/SHA 是哈希,输入相同输出相同。UUID v4 是随机,每次生成不同。v3/v5 是哈希型,但只针对命名空间+名字组合,不是任意哈希。
Q: 工具会记录生成的 UUID 吗?
A: 52tool UUID 生成器在浏览器端生成,不联网不上传。生成的 UUID 不被记录,安全用于密钥、token 等敏感场景。
总结
UUID 是分布式系统的基础设施:
- 通用场景用 v4:52tool UUID 生成器
- 确定性 ID 用 v5
- 时间排序用 v1 或 v7
- 数据库主键考虑 v7
- URL 友好场景用 NanoID
记住:v4 是默认选择,需要确定性时选 v5,需要时间排序时选 v7。