UUID(Universally Unique Identifier,通用唯一标识符)是一个128位的标识符,由开放软件基金会(OSF)在分布式计算环境(DCE)规范中首次定义,后被IETF标准化为RFC 4122,并在2024年更新为RFC 9562。UUID的核心设计理念是:在不需要中央注册机构的情况下,任何人在任何时间、任何地点都能生成一个全球唯一的标识符。这一特性使UUID成为分布式系统、微服务架构和数据库设计中不可或缺的基础组件。
GUID(Globally Unique Identifier,全局唯一标识符)是微软对UUID的称呼。从技术角度来说,GUID和UUID是完全相同的东西——都是128位标识符,使用相同的格式和生成算法。微软在COM、.NET、SQL Server等技术中使用"GUID"这个名称,而其他平台(Linux、Java、Python、Web标准等)通常使用"UUID"。唯一的细微差异是微软在某些场景下会使用大括号包裹GUID,如 {550e8400-e29b-41d4-a716-446655440000},但这只是显示格式的区别。
| 版本 | 生成方式 | 确定性 | 可排序 | 隐私安全 | 推荐场景 |
|---|---|---|---|---|---|
| v1 | 时间戳(60位) + MAC地址 | 否 | 部分 | 差(泄露MAC和时间) | 内部系统、不暴露给外部 |
| v2 | 时间戳 + POSIX UID/GID | 否 | 部分 | 差 | DCE安全场景(极少使用) |
| v3 | 命名空间 + 名称的MD5哈希 | 是 | 否 | 好 | 根据名称生成固定UUID(如URL映射) |
| v4 | 122位密码学安全随机数 | 否 | 否 | 最好 | 最通用,适合绝大多数场景 |
| v5 | 命名空间 + 名称的SHA-1哈希 | 是 | 否 | 好 | 类似v3但更安全,优先于v3使用 |
| v6 | v1改进,时间戳重排列 | 否 | 是 | 差 | 需要时间排序的旧系统迁移 |
| v7 | Unix毫秒时间戳 + 随机数 | 否 | 是 | 较好 | 数据库主键(强烈推荐) |
| v8 | 自定义格式(保留版本/变体位) | 取决于实现 | 取决于实现 | 取决于实现 | 有特殊需求的自定义方案 |
UUID v4拥有122位有效随机位,总共有2^122 ≈ 5.3 × 10^36种可能的值。根据生日悖论(Birthday Paradox),当生成的UUID数量达到约2.71 × 10^18个时,碰撞概率才达到50%。为了直观理解这个数字的含义:
| 场景 | 已生成UUID数量 | 碰撞概率 | 直观比较 |
|---|---|---|---|
| 小型应用 | 100万(10^6) | ≈ 10^-25 | 比连中10次彩票还低 |
| 中型系统 | 10亿(10^9) | ≈ 10^-19 | 比被陨石击中的概率还低 |
| 大型平台 | 1万亿(10^12) | ≈ 10^-13 | 几乎不可能 |
| 极端压力测试 | 10^15 | ≈ 10^-7 | 千万分之一 |
| 理论碰撞点 | 2.71 × 10^18 | ≈ 50% | 每秒10亿个连续生成86年 |
换一个角度:如果全世界80亿人每人每秒生成一个UUID v4,需要连续生成约100亿年(约为宇宙年龄的7倍)才有50%的碰撞概率。所以在工程实践中,UUID v4的碰撞风险可以安全地忽略不计。
UUID作为数据库主键有很多优势(全局唯一、可离线生成、不泄露业务信息),但也有性能上的注意事项:
| 语言/平台 | 生成方式 | 版本 |
|---|---|---|
| JavaScript | crypto.randomUUID() | v4 |
| Python | uuid.uuid4() / uuid.uuid1() | v4 / v1 |
| Java | UUID.randomUUID() | v4 |
| Go | github.com/google/uuid | v1/v4/v6/v7 |
| C#/.NET | Guid.NewGuid() | v4 |
| PostgreSQL | gen_random_uuid() | v4 |
| MySQL 8.0+ | UUID() | v1(注意不是v4) |