指南

UUID:完整指南

通用唯一标识符 (UUID) 是现代软件开发的支柱,为数据库记录、分布式系统和 API 提供保证唯一的标识符。理解不同的 UUID 版本以及何时使用每个版本对于构建可扩展、可靠的应用程序至关重要。

什么是 UUID?

UUID(通用唯一标识符)是一个 128 位的数字,用于唯一标识信息,而无需中央注册机构。标准的 UUID 格式是一个 36 字符的字符串:8-4-4-4-12 个十六进制数字,用破折号分隔,如 550e8400-e29b-41d4-a716-446655440000。 UUID 的强大之处在于其实际的唯一性保证。当正确生成时,两个系统独立创建相同 UUID 的概率接近于零——大约是 1 / 10^36。这使得 UUID 对于分布式系统非常有价值,其中多个服务器或客户端需要生成 ID 而不协调或检查重复。 UUID 解决了几个重要问题。在传统的数据库设计中,自增整数 ID 需要中央数据库分配下一个数字。这在分布式系统中创建了瓶颈和单点故障。使用 UUID,任何系统都可以生成 ID,无需网络往返或协调。这在微服务架构、离线优先应用程序和分布式数据库中尤其有价值。 不同的 UUID 版本针对不同的用例进行了优化。UUID v1 使用时间戳和 MAC 地址,提供时间排序但可能泄漏信息。UUID v4 使用随机数,提供最大的不可预测性。UUID v5(和 v3)使用命名空间和名称的哈希,为相同的输入提供确定性的 UUID。理解这些差异有助于您为您的需求选择正确的版本。 UUID 广泛应用于各个领域。数据库将 UUID 用作主键,特别是在分布式系统中。REST API 使用 UUID 作为资源标识符,提供不可猜测的 URL。消息队列使用 UUID 跟踪消息。文件系统使用 UUID 标识卷和分区。会话令牌、请求跟踪、事件溯源和许多其他领域都依赖 UUID 进行可靠的识别。 虽然 UUID 很强大,但它们也有权衡。它们比整数大(128 位 vs 32 或 64 位),这会影响数据库性能和存储。它们不可读(尝试通过电话大声朗读 UUID!)。某些版本(v1)可能会泄漏时间戳和 MAC 地址。了解这些权衡有助于您明智地使用 UUID。

UUID 版本比较

UUID v1(基于时间)将当前时间戳、时钟序列和 MAC 地址组合成唯一标识符。时间戳组件意味着 UUID v1 可以按时间排序——如果您生成两个 UUID v1,较新的将具有较大的值。这对于某些数据库索引策略和时间序列数据很有用。 然而,UUID v1 有隐私含义。由于它包含生成它的机器的 MAC 地址,因此可以追溯到特定硬件。这曾经在著名的梅丽莎病毒案中被使用,执法部门使用病毒中嵌入的 UUID v1 跟踪作者。现代实现通常使用随机节点 ID 而不是真实的 MAC 地址来缓解这种情况,但如果隐私是一个问题,UUID v1 可能不是最佳选择。 UUID v1 的另一个考虑是时钟序列。如果系统时钟向后移动(由于 NTP 调整或手动更改),UUID v1 生成可能会产生重复。大多数实现通过增加时钟序列计数器来处理这个问题,但这是一个潜在的边缘情况需要注意。 UUID v4(随机)是最广泛使用的版本,原因很简单:简单性和安全性。UUID v4 使用加密安全的随机数生成器填充 122 位随机数据(6 位保留用于版本和变体指示符)。这种随机性确保了不可预测性——您无法猜测下一个 UUID 或推断先前的 UUID,使 v4 对安全敏感应用程序是理想的。 碰撞概率(两个随机 UUID 相同)在天文学上很小。要有 50% 的机会发生单次碰撞,您需要生成约 2.71 万亿个 UUID。对于实际目的,碰撞风险可以忽略不计,尽管关键任务系统可能仍然实施重复检查作为额外的预防措施。 UUID v4 的权衡是缺乏可排序性。与 UUID v1 不同,UUID v4 是随机的,因此创建顺序没有内在的排序。如果您需要可排序的 ID,UUID v4 可能不是最佳选择,除非您添加单独的时间戳字段或考虑 ULID(一种按时间排序的 UUID 的替代方案)等替代方案。 UUID v5(基于名称,使用 SHA-1)和 UUID v3(基于名称,使用 MD5)从命名空间和名称生成确定性 UUID。相同的命名空间和名称始终生成相同的 UUID。这对于幂等性很有用——如果您需要为同一个实体多次生成 UUID(可能在不同系统中),UUID v5 确保您每次都获得相同的 ID。 命名空间可以是任何现有的 UUID,标准命名空间存在于 DNS(6ba7b810-9dad-11d1-80b4-00c04fd430c8)、URL(6ba7b811-9dad-11d1-80b4-00c04fd430c8)、ISO OID(6ba7b812-9dad-11d1-80b4-00c04fd430c8)和 X.500 DN(6ba7b814-9dad-11d1-80b4-00c04fd430c8)。您还可以生成自定义命名空间 UUID。 UUID v5 优于 v3,因为它使用 SHA-1 而不是 MD5(MD5 在密码学上已被破解)。然而,对于大多数 UUID 应用程序,哈希强度的差异可以忽略不计,因为 UUID 不用于密码学。如果您在 v3 和 v5 之间选择,请使用 v5,除非您需要与仅支持 v3 的遗留系统兼容。 使用 UUID v5 时,选择适当的命名空间和名称至关重要。对于基于 URL 的实体,使用 URL 命名空间和完整的 URL。对于域名,使用 DNS 命名空间。对于自定义应用程序实体,创建一个特定于您的应用程序的自定义命名空间 UUID 并对其进行文档化。确保名称是稳定的——如果您更改名称,您将获得不同的 UUID。

选择正确的 UUID 版本

选择正确的 UUID 版本取决于您的特定要求。以下是如何根据您的用例进行决策的指南。 对于通用唯一 ID(数据库主键、API 资源标识符),UUID v4 是默认选择。其随机性确保了不可预测性,这对安全性很有价值——用户无法猜测其他资源 ID。其简单性意味着更少的实现错误。大多数现代框架和数据库都很好地支持 UUID v4。除非您有需要不同版本的特定原因,否则使用 v4。 对于分布式系统和事件溯源,UUID v4 提供了去中心化的 ID 生成,而没有协调。每个节点可以独立生成 ID,而无需网络往返。然而,如果您需要对事件进行时间排序并且不想维护单独的时间戳,UUID v1 可能更合适,因为它具有内在的时间排序。某些事件溯源框架更喜欢 UUID v1 用于此属性。 对于需要确定性 ID 的幂等操作(相同的输入应该总是产生相同的 ID),UUID v5 是理想的。例如,如果您从 URL 导入资源并希望重新导入以更新而不是创建重复,请使用 UUID v5 与 URL 命名空间和 URL 作为名称。重新导入相同的 URL 将生成相同的 UUID,允许您的系统识别它作为更新。 对于缓存键和内容可寻址存储,UUID v5 提供了一致的哈希。给定相同的内容,您始终获得相同的 UUID,允许高效的重复数据删除和缓存命中。Git 内部使用类似的概念(虽然不是 UUID)对内容进行哈希。 对于数据库性能,考虑索引含义。随机 UUID(v4)可能导致 B 树索引的碎片,因为新 ID 不会顺序插入。这可能会影响插入性能和索引大小。UUID v1 的时间排序缓解了这一点,因为较新的 UUID 倾向于具有较高的值。一些数据库(如 PostgreSQL)有 UUID 优化的索引类型。对于高吞吐量系统,对您的工作负载进行基准测试。 对于安全令牌和会话 ID,UUID v4 是必不可少的。其不可预测性防止了攻击者猜测有效令牌。切勿使用 UUID v1 进行会话令牌——其可预测性是一个安全风险。某些应用程序甚至在 UUID v4 之上添加额外的随机性或使用专用的令牌生成库。 对于跨系统的兼容性和迁移,检查现有系统支持什么。大多数系统支持 UUID v4,许多支持 v1,较少支持 v5/v3。如果您正在与外部系统集成,请验证它们可以处理您的 UUID 版本。一些旧系统可能仅接受特定格式或版本。 对于人类可读性,UUID 本质上不可读。如果您需要可读的 ID,请考虑 UUID 的替代方案,如 ULID(按时间排序,base32 编码)、nanoid(更短,可自定义)或自定义方案,如有意义的前缀加 UUID(如 user_550e8400-e29b-41d4-a716-446655440000)。 实际建议:对于大多数 Web 应用程序,UUID v4 是安全、简单的选择。对于需要时间排序的分布式系统,考虑 UUID v1 或 ULID。对于确定性需求,使用 UUID v5。当有疑问时,使用 v4——它很少是错误的选择。

试用工具

UUID生成器

UUID生成器

了解更多

常见问题

UUID生成器

常见问题