什么是 UUID?

UUID(Universally Unique Identifier,通用唯一识别码)是一个 128 位的标识符,用于在分布式系统中唯一标识信息。UUID 的标准形式为 32 个十六进制数字,以连字符分为 5 组,格式为 8-4-4-4-12,例如:550e8400-e29b-41d4-a716-446655440000。

UUID 也被称为 GUID(Globally Unique Identifier),两者本质相同,只是命名来源不同。UUID 由开放软件基金会(OSF)标准化,定义在 RFC 4122 规范中。

UUID 版本说明

UUID v1时间戳

基于时间戳和 MAC 地址生成,包含生成时间和机器标识。

✓ 有序性✓ 可追溯⚠ 隐私风险
UUID v4随机

基于随机数生成,最常用的版本,碰撞概率极低。

✓ 随机性强✓ 无隐私风险推荐使用
UUID v3MD5

基于命名空间和名称的 MD5 哈希生成,确定性。

✓ 可重现✓ 确定性⚠ MD5 弱
UUID v5SHA-1

基于命名空间和名称的 SHA-1 哈希生成,确定性。

✓ 可重现✓ 确定性比 v3 安全

UUID 结构解析

550e8400-e29b-41d4-a716-446655440000
550e8400时间低位 (32位)
e29b时间中位 (16位)
41d4版本+时间高位 (16位)
a716变体+时钟 (16位)
446655440000节点 ID (48位)

编程语言中生成 UUID

JavaScript / Node.js

// Node.js 内置 crypto 模块
const { randomUUID } = require('crypto');
const uuid = randomUUID();
console.log(uuid); // '550e8400-e29b-41d4-a716-446655440000'

// 使用 uuid 库
const { v4: uuidv4, v1: uuidv1 } = require('uuid');
console.log(uuidv4()); // v4 随机 UUID
console.log(uuidv1()); // v1 时间戳 UUID

// 浏览器环境
const uuid = crypto.randomUUID();

// 手动生成 v4 UUID
function generateUUID() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
    const r = Math.random() * 16 | 0;
    const v = c === 'x' ? r : (r & 0x3 | 0x8);
    return v.toString(16);
  });
}

Python

import uuid

# UUID v4(随机)
uuid4 = uuid.uuid4()
print(uuid4)  # 550e8400-e29b-41d4-a716-446655440000

# UUID v1(基于时间戳)
uuid1 = uuid.uuid1()
print(uuid1)

# UUID v3(基于 MD5)
uuid3 = uuid.uuid3(uuid.NAMESPACE_DNS, 'example.com')
print(uuid3)

# UUID v5(基于 SHA-1)
uuid5 = uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com')
print(uuid5)

# 转换为字符串
uuid_str = str(uuid4)

# 从字符串解析
parsed = uuid.UUID('550e8400-e29b-41d4-a716-446655440000')

Java

import java.util.UUID;

// 生成随机 UUID(v4)
UUID uuid = UUID.randomUUID();
System.out.println(uuid); // 550e8400-e29b-41d4-a716-446655440000

// 从字符串创建
UUID parsed = UUID.fromString("550e8400-e29b-41d4-a716-446655440000");

// 获取各部分
long mostSig = uuid.getMostSignificantBits();
long leastSig = uuid.getLeastSignificantBits();

// 转换为字符串
String uuidStr = uuid.toString();

// 获取版本
int version = uuid.version(); // 4

PHP

// 使用 Ramsey/UUID 包(推荐)
use Ramsey\Uuid\Uuid;

$uuid4 = Uuid::uuid4();
echo $uuid4->toString(); // 550e8400-e29b-41d4-a716-446655440000

$uuid1 = Uuid::uuid1();
echo $uuid1->toString();

// 原生 PHP 生成 v4 UUID
function generateUUID() {
    $data = random_bytes(16);
    $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // 版本 4
    $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // 变体
    return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}

echo generateUUID();

Go

import (
    "github.com/google/uuid"
    "fmt"
)

// 生成 UUID v4
id := uuid.New()
fmt.Println(id.String()) // 550e8400-e29b-41d4-a716-446655440000

// 解析 UUID
parsed, err := uuid.Parse("550e8400-e29b-41d4-a716-446655440000")

// 生成 UUID v1
id1 := uuid.Must(uuid.NewUUID())

// 从字节创建
bytes := uuid.NewRandom()
fmt.Println(bytes)

C#

using System;

// 生成 UUID(v4 随机)
Guid guid = Guid.NewGuid();
Console.WriteLine(guid); // 550e8400-e29b-41d4-a716-446655440000

// 从字符串解析
Guid parsed = Guid.Parse("550e8400-e29b-41d4-a716-446655440000");

// 转换格式
Console.WriteLine(guid.ToString("N")); // 无连字符
Console.WriteLine(guid.ToString("D")); // 默认格式
Console.WriteLine(guid.ToString("B")); // 带大括号
Console.WriteLine(guid.ToString("P")); // 带小括号

// 空的 UUID
Guid empty = Guid.Empty;

Ruby

require 'securerandom'

# 生成 UUID v4
uuid = SecureRandom.uuid
puts uuid # "550e8400-e29b-41d4-a716-446655440000"

# 使用 uuidtools gem
require 'uuidtools'

uuid4 = UUIDTools::UUID.random_create
puts uuid4.to_s

uuid1 = UUIDTools::UUID.timestamp_create
puts uuid1.to_s

# 解析 UUID
parsed = UUIDTools::UUID.parse("550e8400-e29b-41d4-a716-446655440000")

Shell / 命令行

# Linux
cat /proc/sys/kernel/random/uuid
# 输出: 550e8400-e29b-41d4-a716-446655440000

# macOS
uuidgen
# 输出: 550E8400-E29B-41D4-A716-446655440000

# 使用 Python
python3 -c "import uuid; print(uuid.uuid4())"

# 使用 Node.js
node -e "console.log(require('crypto').randomUUID())"

# 批量生成
for i in {1..5}; do uuidgen; done

UUID 常见应用场景

🗄️ 数据库主键

作为分布式系统的主键,避免自增 ID 的单点瓶颈

🔐 会话标识

Web 应用的 Session ID、Token 标识

📁 文件命名

上传文件的唯一命名,避免文件名冲突

🔗 短链接

短链接服务的唯一标识符

📦 订单号

电商系统的订单号、交易流水号

📱 设备标识

移动设备、IoT 设备的唯一标识

常见问题

Q: UUID 真的是唯一的吗?

A: UUID v4 基于随机数生成,理论上存在碰撞可能,但概率极低。以 v4 为例,生成 10 亿个 UUID,碰撞概率约为 0.00000000006%。在实际应用中可以认为唯一。

Q: UUID v1 和 v4 该选哪个?

A: 大多数场景推荐 v4。v1 包含机器 MAC 地址和时间戳,可能泄露隐私信息。v4 完全随机,无隐私风险。v1 的优势是时间有序,适合需要按时间排序的场景。

Q: UUID 作为数据库主键有什么优缺点?

A: 优点:分布式友好、无单点瓶颈、合并数据方便。缺点:占用空间大(36字符 vs 自增ID的数字)、索引效率较低、无序导致页分裂。建议使用有序 UUID 或 ULID。

Q: UUID 和 GUID 有什么区别?

A: 本质上没有区别。UUID 是标准名称(RFC 4122),GUID 是微软的命名。格式完全相同,可以互换使用。