UUID 在分布式系统中的应用与最佳实践
在分布式系统中,生成全局唯一标识符是一个核心问题。UUID 是最常见的解决方案之一。
什么是 UUID?
UUID(Universally Unique Identifier)是 128 位的全局唯一标识符。
550e8400-e29b-41d4-a716-446655440000
格式
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
M = 版本号(1-5)
N = 变体(8, 9, a, b)
UUID 版本
| 版本 | 生成方式 | 特点 |
|---|---|---|
| V1 | 时间戳 + MAC 地址 | 有序,但暴露 MAC 地址 |
| V3 | MD5 哈希 | 基于命名空间和名称 |
| V4 | 随机数 | 最常用,完全随机 |
| V5 | SHA-1 哈希 | 基于命名空间和名称 |
生成 UUID
Java
import java.util.UUID;
// V4(随机)
UUID uuid = UUID.randomUUID();
// 550e8400-e29b-41d4-a716-446655440000
// 转为字符串
String uuidStr = uuid.toString();
JavaScript
// 浏览器
crypto.randomUUID();
// '36b8f84d-df4e-4d49-b662-bcde71a8764f'
// Node.js
const { v4: uuidv4 } = require('uuid');
uuidv4();
Python
import uuid
# V4
uuid.uuid4()
# UUID('550e8400-e29b-41d4-a716-446655440000')
UUID 的优势
1. 全局唯一
128 位空间,碰撞概率极低:
2^128 = 340,282,366,920,938,463,463,374,607,431,768,211,456
即使每秒生成 10 亿个 UUID,也需要 100 亿年才会碰撞。
2. 无需中心协调
每个节点独立生成,无需协调。
3. 可离线生成
不依赖数据库或网络。
UUID 的劣势
1. 存储空间大
128 位(16 字节),比自增 ID(4-8 字节)大。
2. 无序
V4 完全随机,作为主键时:
- B+ 树插入性能差
- 页分裂频繁
- 索引碎片化
3. 可读性差
550e8400-e29b-41d4-a716-446655440000 vs 12345
分布式 ID 方案对比
| 方案 | 有序 | 性能 | 依赖 | 适用场景 |
|---|---|---|---|---|
| UUID V4 | ❌ | 高 | 无 | 通用 |
| UUID V1 | ✅ | 高 | 无 | 需要有序 |
| Snowflake | ✅ | 极高 | ZooKeeper | 高性能 |
| 数据库自增 | ✅ | 中 | 数据库 | 单库 |
| Redis | ✅ | 高 | Redis | 中等规模 |
优化方案
1. 有序 UUID(UUID V1)
// 使用时间戳生成有序 UUID
UUID uuid = UUID.randomUUID(); // 替换为 V1
2. ULID(Universally Unique Lexicographically Sortable Identifier)
01ARZ3NDEKTSV4RRFFQ69G5FAV
特点:
- 128 位,兼容 UUID
- 前 48 位是时间戳,有序
- 可排序
3. Snowflake(雪花算法)
// 64 位 ID
// 1位符号 + 41位时间戳 + 10位机器ID + 12位序列号
long id = snowflake.nextId();
数据库存储优化
方案一:CHAR(36)
CREATE TABLE users (
id CHAR(36) PRIMARY KEY,
name VARCHAR(100)
);
方案二:BINARY(16)
-- 节省空间
CREATE TABLE users (
id BINARY(16) PRIMARY KEY,
name VARCHAR(100)
);
方案三:VARCHAR(36) + 索引
CREATE TABLE users (
id VARCHAR(36) PRIMARY KEY,
name VARCHAR(100),
INDEX idx_id (id)
);
最佳实践
- 默认使用 UUID V4:简单可靠
- 需要有序时用 ULID 或 V1:数据库友好
- 高性能场景用 Snowflake:分布式高并发
- 存储优化:使用 BINARY(16) 节省空间
- 索引优化:避免 UUID 作为聚簇索引
总结
UUID 是分布式系统中最简单的全局唯一 ID 方案。根据具体需求选择合适的版本和优化策略,可以在保证唯一性的同时优化性能。