UUID 生成完全指南
UUID(Universally Unique Identifier,通用唯一标识符)是软件开发中广泛使用的标识符标准。本文将全面介绍UUID的概念、版本区别、生成方法和最佳实践。
什么是UUID?
UUID是一个128位的标识符,格式为8-4-4-4-12的十六进制字符串,例如:
550e8400-e29b-41d4-a716-446655440000
UUID的设计目标是在分布式系统中无需中央协调即可生成全局唯一的标识符。这意味着不同机器、不同应用可以独立生成UUID而几乎不会产生冲突。
UUID的版本对比
UUID v1 — 基于时间戳和MAC地址
UUID v1结合时间戳和节点标识(通常是MAC地址)生成。优点是可追溯生成时间和机器,缺点是可能泄露MAC地址信息。
UUID v4 — 随机生成
UUID v4完全基于随机数生成,是最常用的版本。碰撞概率约为1/2^122,生成10亿个UUID的碰撞概率仍可忽略不计。
// JavaScript生成UUID v4
function uuidV4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
const r = Math.random() * 16 | 0
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16)
})
}
UUID v7 — 时间排序
UUID v7是RFC 9562新标准,基于Unix时间戳毫秒级前缀+随机数。最大优势是可排序,适合数据库主键(减少B-tree页分裂)。
# Python生成UUID v7
import uuid
import time
def uuid_v7():
ms = int(time.time() * 1000)
rand = uuid.uuid4().int & ((1 << 74) - 1)
return uuid.UUID(int=(ms << 74) | (0x7 << 72) | rand)
各语言生成UUID的方法
JavaScript:
// 使用crypto API(推荐)
crypto.randomUUID()
// 使用第三方库
import { v4 as uuidv4 } from 'uuid'
uuidv4()
Python:
import uuid
uuid.uuid4() # 随机UUID
uuid.uuid1() # 时间戳UUID
Java:
UUID.randomUUID() // 标准UUID v4
Go:
import "github.com/google/uuid"
id := uuid.New() // UUID v4
UUID的使用场景
1. 数据库主键
UUID常用于分布式数据库的主键,避免自增ID在多节点环境中的冲突问题。推荐使用UUID v7以获得更好的索引性能。
2. API接口标识符
RESTful API中使用UUID作为资源标识符,比自增ID更安全,避免了资源枚举攻击。
3. 会话Token
Web应用中生成会话ID或CSRF Token,UUID的随机性保证了安全性。
4. 分布式系统消息ID
在消息队列、事件驱动架构中,UUID用于唯一标识每条消息或事件。
5. 文件命名
生成唯一的临时文件名,避免文件名冲突。
UUID vs 自增ID
| 特性 | UUID | 自增ID |
|---|---|---|
| 唯一性 | 全局唯一 | 单库唯一 |
| 长度 | 128位 | 64位 |
| 是否有序 | v4无序,v7有序 | 有序 |
| 分布式支持 | 原生支持 | 需要协调 |
| 安全性 | 不可枚举 | 可枚举 |
| 索引性能 | v4较差,v7好 | 好 |
最佳实践
- 优先选择UUID v7 — 既有UUID的全局唯一性,又有自增ID的排序优势
- 数据库存储优化 — 可将UUID存储为BINARY(16)而非VARCHAR(36),节省空间
- 避免使用UUID v1 — MAC地址泄露风险,且时钟回拨可能产生重复
- 批量生成时预分配 — 减少随机数生成开销
- 标准化格式 — 统一使用小写、带连字符的标准格式
总结
UUID是现代软件开发中不可或缺的工具。对于大多数场景,UUID v4足够使用;对于需要排序的数据库主键场景,推荐使用UUID v7。理解各版本的特点,选择合适的生成方式,才能充分发挥UUID的优势。