2. Motivation (动机)
2. Motivation (动机)
使用 UUID 的主要原因之一是不需要中央管理机构来管理它们 (尽管两种格式可能利用可选的 IEEE 802 Node ID, 但其他格式则不需要)。因此, 按需生成可以完全自动化, 并用于各种目的。这里描述的 UUID 生成算法支持非常高的分配速率, 如有必要, 每台机器每秒可达 1000 万个或更多, 因此它们甚至可以用作事务 ID。
UUID 具有固定大小 (128 位), 与其他替代方案相比, 这个大小相当小。这非常适合各种排序、排列和散列; 存储在数据库中; 简单分配; 以及一般的编程便利性。
由于 UUID 是唯一且持久的, 它们成为出色的 URN。无需注册过程即可生成新 UUID 的独特能力使 UUID 成为铸造成本最低的 URN 之一。
2.1 Update Motivation (更新动机)
自 UUID 最初创建以来, 许多事情都发生了变化。现代应用程序需要创建和利用 UUID 作为复杂计算系统中各种不同项目的主要标识符, 包括但不限于数据库键、文件名、机器或系统名称以及事件驱动事务的标识符。
UUID 获得普及的一个领域是数据库键。这源于现代应用程序日益分布式的性质。在这种情况下, 数据库经常使用的 "自动递增" 方案效果不佳: 跨网络协调顺序数字标识符所需的工作量很容易成为负担。UUID 可以在分布式系统中创建唯一的、相当短的值而无需协调, 这一事实使它们成为一个很好的替代方案, 但最初由 [RFC4122] 定义的 UUID 版本 1-5 缺乏某些其他理想的特性, 例如:
-
不按时间排序的 UUID 版本 (如 UUIDv4, 在第 5.4 节中描述) 具有较差的数据库索引局部性。这意味着连续创建的新值在索引中彼此不接近; 因此, 它们需要在随机位置执行插入。由此产生的对用于此目的的常见结构 (B 树及其变体) 的负面性能影响可能是巨大的。
-
UUIDv1 时间戳 (在第 5.1 节中描述) 中使用的 100 纳秒格里高利历元不常见, 并且难以使用标准数字格式 (如 [IEEE754] 中描述的格式) 准确表示。
-
需要内省/解析才能按时间序列排序, 而不是能够执行简单的逐字节比较。
-
在 UUIDv1 的节点字段中使用 Media Access Control (媒体访问控制, MAC) 地址会产生隐私和网络安全问题。暴露的 MAC 地址可以用作攻击面来定位网络接口并揭示有关此类机器的各种其他信息 (至少是制造商, 还可能包括其他详细信息)。此外, 随着虚拟机和容器的出现, MAC 地址的唯一性不再得到保证。
-
[RFC4122] 中指定的许多实现细节涉及的权衡既不可能为所有应用程序指定, 也不是产生可互操作实现所必需的。
-
[RFC4122] 没有区分生成 UUID 的要求和简单存储 UUID 的要求, 尽管它们通常是不同的。
由于上述问题, 许多广泛分布的数据库应用程序和大型应用程序供应商试图解决创建更好的基于时间的、可排序的唯一标识符以用作数据库键的问题。这导致在过去 10 多年中出现了许多实现, 以略有不同的方式解决相同的问题。
在准备本规范时, 分析了以下 16 种不同的实现, 以了解总 ID 长度、位布局、词法格式和编码、时间戳类型、时间戳格式、时间戳精度、节点格式和组件、冲突处理以及多时间戳滴答生成序列的趋势:
- [ULID]
- [LexicalUUID]
- [Snowflake]
- [Flake]
- [ShardingID]
- [KSUID]
- [Elasticflake]
- [FlakeID]
- [Sonyflake]
- [orderedUuid]
- [COMBGUID]
- [SID]
- [pushID]
- [XID]
- [ObjectID]
- [CUID]
对这些实现和上述问题的检查导致了本文档, 其中新的 UUID 被调整以解决这些问题。
此外, [RFC4122] 本身需要进行全面改革以解决许多主题, 包括但不限于以下内容:
-
实施各种勘误报告。主要围绕位布局澄清, 这导致了不一致的实现 [Err1957], [Err3546], [Err4975], [Err4976], [Err5560] 等。
-
将其他 UUID 版本与 UUIDv1 位布局解耦, 以便在不基于时间的 UUID 中不需要引用 "time_hi_and_version" 等字段, 同时为 UUIDv3, UUIDv4 和 UUIDv5 提供类似于 UUIDv1 的定义部分。
-
围绕现有和原型实现观察到的许多实际场景和边缘情况提供实施最佳实践。
-
解决现代时代的安全最佳实践和考虑事项, 因为它涉及 MAC 地址、散列算法、安全随机性和其他主题。
-
为实现提供基于标准的选项, 用于特定于实现和/或实验性 UUID 设计。
-
提供更多测试向量, 说明根���规范创建的真实 UUID。