通用唯一标识符(UUID)是用于在计算机系统中唯一标识信息的128位数字。它们对于分布式系统、数据库设计和现代软件架构至关重要。本指南将全面介绍关于UUID的所有知识。
目录
核心要点
- 通用性:UUID设计为在空间和时间上唯一,无需中央协调。
- 128位:UUID是128位数字,通常显示为带连字符的32个十六进制字符。
- 多个版本:UUID v4(随机)最常用;UUID v1(基于时间)适用于排序。
- 碰撞概率:生成重复UUID v4的概率极低(约2^122分之一)。
- 数据库主键:UUID非常适合分布式数据库主键。
- 隐私性:UUID v4不会泄露创建时间或位置信息。
需要快速生成UUID?试试我们支持多种版本和格式的免费在线工具。
什么是UUID?
UUID(Universally Unique Identifier,通用唯一标识符),在微软系统中也称为GUID(Globally Unique Identifier,全局唯一标识符),是一个128位的标识符,在所有设备和所有时间上都是唯一的。UUID由RFC 4122标准化,在软件开发中被广泛使用。
UUID的关键特性:
- 唯一性:每个UUID几乎可以保证是唯一的
- 去中心化:生成UUID不需要中央权威机构
- 可移植性:UUID可以在任何系统上生成,无需协调
UUID结构和格式
UUID通常表示为32个十六进制数字,分成五组,用连字符分隔:
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
例如:
550e8400-e29b-41d4-a716-446655440000
结构分解如下:
| 部分 | 长度 | 描述 |
|---|---|---|
| time_low | 8字符 | 时间的低32位 |
| time_mid | 4字符 | 时间的中16位 |
| time_hi_and_version | 4字符 | 时间的高12位 + 4位版本号 |
| clock_seq_hi_and_reserved | 2字符 | 时钟序列高位 + 变体 |
| clock_seq_low | 2字符 | 时钟序列低位 |
| node | 12字符 | 48位节点标识符 |
M位置表示UUID版本(1-5),N位置表示变体(RFC 4122 UUID通常为8、9、a或b)。
UUID版本详解
UUID v1(基于时间)
UUID v1使用当前时间戳和计算机的MAC地址生成。
结构:
- 60位时间戳(自1582年10月15日以来的100纳秒间隔)
- 14位时钟序列(处理时钟调整)
- 48位节点ID(通常是MAC地址)
优点:
- 可按创建时间排序
- 在单台机器上保证唯一性
- 可以提取创建时间戳
缺点:
- 泄露MAC地址(隐私问题)
- 泄露创建时间
- 需要访问MAC地址
示例:
6ba7b810-9dad-11d1-80b4-00c04fd430c8
^
版本1
UUID v4(随机)
UUID v4使用随机或伪随机数生成。这是最常用的版本。
结构:
- 122个随机位
- 4位用于版本(0100)
- 2位用于变体(10)
优点:
- 生成简单
- 无隐私问题
- 无硬件依赖
- 适用于任何环境
缺点:
- 不能按时间排序
- 碰撞概率略高(但仍可忽略不计)
示例:
f47ac10b-58cc-4372-a567-0e02b2c3d479
^
版本4
其他UUID版本
| 版本 | 名称 | 描述 |
|---|---|---|
| v2 | DCE安全 | 很少使用,包含POSIX UID/GID |
| v3 | 基于名称(MD5) | 使用MD5从命名空间+名称生成 |
| v5 | 基于名称(SHA-1) | 使用SHA-1从命名空间+名称生成 |
| Nil | 空UUID | 全零:00000000-0000-0000-0000-000000000000 |
代码示例
JavaScript
// 使用 crypto.randomUUID()(现代浏览器和Node.js 14.17+)
const uuid = crypto.randomUUID();
console.log(uuid); // 例如:"f47ac10b-58cc-4372-a567-0e02b2c3d479"
// 手动生成UUID v4(兼容方案)
function generateUUIDv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
// 使用uuid库
// npm install uuid
import { v4 as uuidv4, v1 as uuidv1 } from 'uuid';
const randomUUID = uuidv4(); // 随机UUID
const timeUUID = uuidv1(); // 基于时间的UUID
Python
import uuid
# 生成UUID v4(随机)
random_uuid = uuid.uuid4()
print(random_uuid) # 例如:f47ac10b-58cc-4372-a567-0e02b2c3d479
# 生成UUID v1(基于时间)
time_uuid = uuid.uuid1()
print(time_uuid)
# 生成UUID v5(基于名称,使用SHA-1)
namespace = uuid.NAMESPACE_DNS
name_uuid = uuid.uuid5(namespace, 'example.com')
print(name_uuid)
# 转换为不同格式
uuid_str = str(random_uuid) # 字符串格式
uuid_hex = random_uuid.hex # 无连字符
uuid_bytes = random_uuid.bytes # 16字节
uuid_int = random_uuid.int # 128位整数
Java
import java.util.UUID;
public class UUIDExample {
public static void main(String[] args) {
// 生成UUID v4(随机)
UUID randomUUID = UUID.randomUUID();
System.out.println(randomUUID);
// 从字符串解析UUID
UUID parsedUUID = UUID.fromString("550e8400-e29b-41d4-a716-446655440000");
// 获取UUID组件
long mostSigBits = randomUUID.getMostSignificantBits();
long leastSigBits = randomUUID.getLeastSignificantBits();
int version = randomUUID.version(); // v4返回4
int variant = randomUUID.variant(); // RFC 4122返回2
// 转换为无连字符的字符串
String uuidWithoutHyphens = randomUUID.toString().replace("-", "");
}
}
UUID最佳实践
1. 选择正确的版本
| 使用场景 | 推荐版本 |
|---|---|
| 通用用途 | UUID v4 |
| 需要时间排序 | UUID v1 或 ULID |
| 确定性生成 | UUID v5 |
| 隐私敏感 | UUID v4 |
2. 数据库考虑
-- PostgreSQL:使用原生UUID类型
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(100)
);
-- MySQL:使用BINARY(16)以获得更好的性能
CREATE TABLE users (
id BINARY(16) PRIMARY KEY,
name VARCHAR(100)
);
3. 性能技巧
- 谨慎索引:UUID索引可能很大;考虑使用部分索引
- 使用二进制存储:存储为BINARY(16)而不是VARCHAR(36)
- 考虑替代方案:对于高性能需求,考虑ULID或Snowflake ID
4. 安全考虑
- 不要单独使用UUID作为安全令牌
- UUID v1会泄露时间戳和MAC地址
- 使用安全生成器时,UUID v4是加密随机的
常见使用场景
-
数据库主键
- 无需协调的分布式数据库
- 合并来自多个来源的数据
- 避免顺序ID猜测
-
会话标识符
- Web会话令牌
- API请求关联ID
-
文件和资源命名
- 上传的文件名
- 临时文件标识符
-
分布式系统
- 消息队列标识符
- 微服务请求追踪
- 事件溯源
-
API设计
- REST API中的资源标识符
- 幂等性键
常见问题
UUID碰撞的概率是多少?
对于UUID v4,碰撞概率约为2^122分之一(约5.3 x 10^36)。要有50%的碰撞概率,你需要生成约2.71万亿亿个UUID。在实际应用中,UUID碰撞几乎是不可能的。
应该使用UUID v1还是v4?
大多数应用推荐使用UUID v4,因为它简单且保护隐私。只有在需要基于时间排序或需要提取创建时间戳时才使用UUID v1。
UUID适合作为数据库主键吗?
是的,UUID非常适合分布式数据库。但需要考虑以下权衡:
- 优点:无需协调、全局唯一、适合分片
- 缺点:比整数大(16字节 vs 4-8字节)、随机UUID可能导致索引碎片
如何不写代码生成UUID?
你可以使用在线工具,如我们的免费UUID生成器,无需编写任何代码即可快速生成各种格式的UUID。
UUID和GUID有什么区别?
UUID和GUID本质上是同一个东西。GUID(Globally Unique Identifier,全局唯一标识符)是微软对UUID的称呼。两者都遵循相同的RFC 4122标准。
总结
UUID是现代软件开发中的基础工具,提供了一种无需中央协调即可生成唯一标识符的可靠方法。了解不同版本及其权衡有助于你为特定用例做出明智的决策。
快速总结:
- 大多数通用应用使用UUID v4
- 需要基于时间排序时使用UUID v1
- 需要确定性、可重复的标识符时使用UUID v5
- 数据库使用时考虑存储格式和索引策略
准备好生成UUID了吗?试试我们的免费在线工具: