调度 BGP。 PeabodyInternet-DraftUpdates:4122(如果获得批准)K. DavisIntended status:Standard Track 26 April 2021Expires:28 October 2021 New UUID Formats draft-peabody-dispatch-new-uuid-format-01Abstract 本文档介绍了新的基于时间的 UUID 格式,这些格式是适合用作数据库密钥。现代应用程序的常见情况是创建唯一标识符以用作数据库表中的主键。该标识符通常实现一个嵌入式时间戳,该时间戳可以使用最高有效位中的单调创建时间进行排序。此外,标识符具有很强的抗冲突性,难以猜测,并提供最小的安全攻击面。现有的 UUID 版本(包括 UUIDv1)都没有以最有效的方式满足这些要求中的每一个。本文档是一份更新 [RFC4122] 的提案,使用三个新的 UUID 版本来解决这些问题,每个版本都有不同的权衡。本备忘录的状态 本互联网草案的提交完全符合 BCP 78 和 BCP 79 的规定。 Internet-Drafts 是 Internet Engineering Task Force (IETF) 的工作文件。请注意,其他组也可以将工作文档作为 Internet 草案分发。当前互联网草案的列表位于 https://datatracker.ietf.org/drafts/current/。 Internet-Drafts 是有效期最长为六个月的草稿文件,可以随时更新、替换或被其他文件淘汰。将互联网草案用作参考材料或引用它们而不是“正在进行的工作”是不合适的。此互联网草案将于 2021 年 10 月 28 日到期。版权声明 版权所有 (c) 2021 IETF Trust 和确定为文档作者的人员。版权所有。 Peabody & Davis 于 2021 年 10 月 28 日到期 [Page 1] Internet-Draft new-uuid-format 2021 年 4 月 本文档受 BCP 78 和 IETF Trust 与 IETF 文档相关的法律规定的约束 ( https://trustee.ietf.org/ license -info) 在本文档发布之日生效。请仔细阅读这些文件,因为它们描述了您对本文件的权利和限制。从本文档中提取的代码组件必须包含 Trust Legal Provisions 第 4.e 节中所述的简化 BSD 许可文本,并且不提供如简化 BSD 许可中所述的保证。目录 1. 介绍 。 . . . . . . . . . . . . . . . . . . . . . . . 2 2. 背景。 . . . . . . . . . . . . . . . . . . . . . . . . 3 3. 变更概要。 . . . . . . . . . . . . . . . . . . . . 5 4. 格式。 . . . . . . . . . . . . . . . . . . . . . . . . . . 6 4.1.版本。 . . . . . . . . . . . . . . . . . . . . . . . 6 4.2.变体。 . . . . . . . . . . . . . . . . . . . . . . . . 6 4.3. UUIDv6 布局和位顺序。 . . . . . . . . . . . . . . 7 4.3.1. UUIDv6 时间戳用法。 . . . . . . . . . . . . . . 8 4.3.2. UUIDv6 时钟序列用法。 . . . . . . . . . . . . 8 4.3.3. UUIDv6 节点使用。 . . . . . . . . . . . . . . . . . 8 4.3.4. UUIDv6 基本创建算法。 . . . . . . . . . . 8 4.4. UUIDv7 布局和位顺序。 . . . . . . . . . . . . . . 10 4.4.1. UUIDv7 时间戳用法。 . . . . . . . . . . . . . . 11 4.4.2. UUIDv7 时钟序列用法。 . . . . . . . . . . . . 11 4.4.3. UUIDv7 节点使用。 . . . . . . . . . . . . . . . . . 11 4.4.4. UUIDv7 编码和解码。 . . . . . . . . . . . 11 4.5。 UUIDv8 布局和位顺序。 . . . . . . . . . . . . . . 16 4.5.1. UUIDv8 时间戳用法。 . . . . . . . . . . . . . . 18 4.5.2. UUIDv8 时钟序列用法。 . . . . . . . . . . . . 20 4.5.3. UUIDv8 节点使用。 . . . . . . . . . . . . . . . . . 20 4.5.4. UUIDv6 基本创建算法。 . . . . . . . . . . 21 5. 编码和存储。 . . . . . . . . . . . . . . . . . . . 24 6. 全球唯一性。 . . . . . . . . . . . . . . . . . . . . . 24 7. 分布式 UUID 生成。 . . . . . . . . . . . . . . . . 24 8. IANA 考虑因素。 . . . . . . . . . . . . . . . . . . . . 25 9. 安全考虑。 . . . . . . . . . . . . . . . . . . 25 10. 致谢。 . . . . . . . . . . . . . . . . . . . . . 25 11. 规范性参考文献。 . . . . . . . . . . . . . . . . . . . 25 12. 参考资料。 . . . . . . . . . . . . . . . . . . 26 作者的地址。 . . . . . . . . . . . . . . . . . . . . . . 27 1. 介绍关键词“必须”、“不得”、“要求”、“应该”、“不应该”、“应该”、“不应该”、“推荐”、“可以”和“可选”本文档中的内容将按照 [RFC2119] 中的描述进行解释。 Peabody & Davis 于 2021 年 10 月 28 日到期 [Page 2] Internet-Draft new-uuid-format 2021 年 4 月 2. 背景 自 UUID 最初创建以来,很多事情都发生了变化。现代应用程序需要使用(并且许多已经实现)UUID 作为数据库主键。使用 UUID 作为数据库键的动机主要源于应用程序在本质上越来越分布式的事实。具有整数顺序的简单“自动增量”方案在分布式系统中不能很好地工作,因为在网络上同步这些数字所需的工作很容易成为负担。 UUID 可用于在分布式系统中创建唯一且合理的短值而无需同步,这一事实使它们成为此类环境中用作数据库键的良好候选者。然而,[RFC4122] UUID 的某些属性不太适合此任务。首先,大多数现有的 UUID 版本(例如 UUIDv4)的数据库索引局部性较差。这意味着连续创建的新值在索引中彼此不接近,因此需要在随机位置执行插入。其对用于此的常见结构(B 树及其变体)的负面性能影响可能是巨大的。因此,新插入的值应该按时间排序来解决这个问题。虽然 UUIDv1 确实包含嵌入式时间戳并且可以按时间排序; UUIDv1 还有其他问题。可以按时间对版本 1 UUID 进行排序,但这是一项费力的任务。该过程需要将 UUID 的字节分成不同的部分,重新排列位,然后根据重建的时间戳确定顺序。这在非常大的系统中效率不高。实现将通过排序顺序进行简化,其中 UUID 可以简单地视为不透明的字节序列并按顺序排序。在嵌入时间戳之后,其余 64 位本质上用于在全球范围内和给定时间戳记内提供唯一性。时钟序列值确保当为同一个时间戳值生成多个 UUID 时,会给出一个单调序列值。这种显式排序有助于进一步促进排序。剩余的随机位确保冲突最小。 Peabody & Davis 将于 2021 年 10 月 28 日到期 [第 3 页] Internet-Draft new-uuid-format 2021 年 4 月 此外,UUIDv1 使用源自公历的非标准时间戳纪元。更具体地说,协调世界时 (UTC) 作为自 1582 年 10 月 15 日 00:00:00.00 以来的 100 纳秒间隔的计数。 epoch 或其他具有应用程序所需的各种时间戳精度级别的时间戳源。最后,在版本 1 UUID 的节点字段中使用 MAC 地址会引起隐私和网络安全问题。暴露的 MAC 地址可用作攻击面来定位机器并揭示有关此类机器的各种其他信息(最低限度是制造商,可能还有其他详细信息)。相反,“密码安全”伪随机数生成器 (CSPRNG) 或伪随机数生成器 (PRNG) 应该在应用程序上下文中使用,以提供唯一性和不可猜测性。由于到目前为止 UUIDv1 和 UUIDv4 细节的缺点,许多分布广泛的数据库应用程序和大型应用程序供应商都在寻求解决创建一个更好的基于时间、可排序的唯一标识符作为数据库键的问题。这导致在过去 10 多年中以略有不同的方式解决同一问题的大量实现。在准备本规范时,对以下 16 种不同的实现进行了分析,以了解总 ID 长度、位布局、词汇格式/编码、时间戳类型、时间戳格式、时间戳准确性、节点格式/组件、冲突处理和多时间戳记号生成序列的趋势。 1. [LexicalUUID] 来自 Twitter 2. [Snowflake] 来自 Twitter 3. [Flake] 来自 Boundary 4. [ShardingID] 来自 Instagram 5. [KSUID] 来自 Segment 6. [Elasticflake] 来自 P. Pearcy 7. [FlakeID] 来自T. Pawlak 8. [Sonyflake] 由 Sony 9. [orderedUuid] 由 IT。 Cabrera 10. [ COMBGUID] R. Tallent 11. [ ULID] A. Feerasta 12. [ SID] A. Chilton 13. [ pushID ] Google 14. [ XID ] O. Poitrey 15. [ ObjectID] MongoDB 16. [CUID] 由 E. Elliott Peabody & Davis 于 2021 年 10 月 28 日到期 [第 4 页] Internet-Draft new-uuid-format 2021 年 4 月 对这些实现的检查详细说明了以下有助于定义该标准的趋势: - 时间戳必须是k-可排序的。也就是说,相同时间戳内或接近相同时间戳的值通过排序算法正确排序。 - 时间戳应该是 big-endian,按原样嵌入时间的最重要位,无需重新排序。 - 时间戳应该使用毫秒精度和 Unix Epoch 作为时间戳源。虽然,根据应用程序要求,在实现之间存在一些变化。 - 在文本表示中,ID 格式应该是可按字典顺序排序的。 - ID 必须确保正确的嵌入顺序,以便在给定时间戳期间创建多个 UUID 时进行排序。 - ID 不得要求唯一的网络标识符作为实现唯一性的一部分。 - 分布式节点必须能够在不咨询集中资源的情况下创建抗冲突的唯一 ID。 3. 变更摘要 为了解决这些挑战,本规范引入了三个新版本标识符,分配给基于时间的 UUID。第一个 UUIDv6 旨在为已经实现 UUIDv1 的应用程序最容易实现。 UUIDv6 规范保留原始公历时间戳源,但不会按照 UUIDv1 使用的过程对时间戳位重新排序。 UUIDv6 还要求必须使用伪随机数据代替 MAC 地址。其余的 UUIDv1 格式在 UUIDv6 中保持不变。参见第 4.3 节 接下来,UUIDv7 引入了一种全新的基于时间的 UUID 位布局,它利用来自广泛实施和众所周知的 Unix Epoch 时间戳源的可变长度时间戳。时间戳被分解为一个 36 位整数部分,然后是一个可变长度的字段,它表示亚秒时间戳部分,编码以便从最高到最低有效的每一位都增加了更高的精度。请参阅第 4.4 节 最后,UUIDv8 引入了一种宽松的基于时间的 UUID 格式,以迎合无法使用 UUIDv1、UUIDv6 或 UUIDv7 的应用程序实现。 UUIDv8 还通过允许来自尚未定义的时间戳源的基于时间的 UUID 格式来验证该规范的未来。可变大小的时间戳提供了很大的灵活性来创建特定于实现的 RFC 兼容基于时间的 UUID,同时保留使 UUID 出色的属性。请参阅第 4.5 节 Peabody & Davis 于 2021 年 10 月 28 日到期 [第 5 页] Internet-Draft new-uuid-format 2021 年 4 月 4. 格式 16 个八位字节(128 位)的 UUID 长度保持不变。由 8-4-4-4-12 格式的 36 个十六进制和破折号字符组成的 UUID 的文本表示保持不变,以提高人类可读性。此外,版本和变体位的位置在布局中保持不变。 4.1.版本 表 1 定义了在给定 UUID 中的第 48 位到第 51 位中找到的 4 位版本。 +------+------+------+------+-------+------- ------------+ | msb0 | msb1 | msb2 | msb3 |版本 |说明 | +------+------+------+------+-------+------- ------------+ | 0 | 1 | 1 | 0 | 6 |重新排序的公历| | | | | | |基于时间的 UUID | +------+------+------+------+-------+------- ------------+ | 0 | 1 | 1 | 1 | 7 |可变长度 Unix | | | | | | |基于纪元时间的 UUID | +------+------+------+------+-------+------- ------------+ | 1 | 0 | 0 | 0 | 8 |自定义基于时间 | | | | | | | UUID | +------+------+------+------+-------+------- ------------+ 表 1:本规范 4.2 定义的 UUID 版本。变体 本规范中 UUID 使用的变体位与 [RFC4122] 第 4.1.1 节相同。表 2 列出了变体字段的内容,第 64 位和第 65 位,其中字母“x”表示“无关”值。常见的十六进制值 8 (1000)、9 (1001)、A (1010) 和 B (1011) 频繁出现在文本表示中。 +------+------+------+---------------------------- -------------+ | msb0 | msb1 | msb2 |说明 | +------+------+------+---------------------------- -------------+ | 1 | 0 | × |本文档中指定的变体。 | +------+------+------+---------------------------- -------------+ 表 2:本规范定义的 UUID 变体 Peabody & Davis 将于 2021 年 10 月 28 日到期 [第 6 页] Internet-Draft new-uuid-format 2021 年 4 月 4.3。 UUIDv6 布局和位顺序 UUIDv6 旨在通过重用 UUIDv1 中的大部分位布局来最容易实现,但更改了时间戳的位顺序。其中 UUIDv1 将时间戳位拆分为三个不同的部分,并将它们排序为 time_low、time_mid、time_high_and_version。 UUIDv6 而是保持时间戳中的源位完整,并将顺序更改为 time_high、time_mid 和 time_low。顺便说一句,这将匹配原始的 60 位格里高利时间戳源。时钟序列位在 [RFC4122] 中的用法和位置保持不变。 48 位节点必须设置为伪随机值。 16 字节、128 位 UUIDv6 的格式如图 1 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+-+-+-+-+-+-+-+-+ | time_high | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- +-+-+-+-+-+-+-+ | time_mid | time_low_and_version | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- +-+-+-+-+-+-+-+ |clk_seq_hi_res | clk_seq_low |节点 (0-1) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- +-+-+-+-+-+-+-+ |节点 (2-5) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- +-+-+-+-+-+-+-+ 图 1:UUIDv6 字段和位布局 time_high:60 位起始时间戳的最高 32 位。占用位 0 到 31(八位字节 0-3) time_mid:60 位起始时间戳的中间 16 位。占用第 32 至 47 位(八位字节 4-5) time_low_and_version:前四个最高有效位必须包含 UUIDv6 版本 (0110),而其余 12 位将包含来自 60 位起始时间戳的最低有效 12 位。占用位 48 到 63(八位字节 6-7) clk_seq_hi_res:前两位必须设置为 UUID 变体 (10) 其余 6 位包含时钟序列的高位部分。占用第 64 位到第 71 位(八位字节 8) Peabody & Davis 2021 年 10 月 28 日到期 [第 7 页]
Internet-Draft new-uuid-format 2021 年 4 月 clock_seq_low:时钟序列的 8 位低部分。占用位 72 到 79(八位字节 9)节点:用作空间唯一标识符的 48 位伪随机数占用位 80 到 127(八位字节 10-15) 4.3.1。 UUIDv6 时间戳用法 UUIDv6 重用 60 位格里高利时间戳,精度为 100 纳秒,在 [RFC4122] 第 4.1.4 节中定义。 4.3.2. UUIDv6 时钟序列用法 UUIDv6 不会更改 [RFC4122] 第 4.1.5 节定义的时钟序列用法。 4.3.3. UUIDv6 节点使用 UUIDv6 节点位应该设置为 48 位随机或伪随机数。 UUIDv6 节点不应使用 IEEE 802 MAC 地址或 [RFC4122],第 4.5 节生成随机多播 IEEE 802 MAC 地址的方法。 4.3.4. UUIDv6 基本创建算法 以下实现算法基于 [RFC4122],但有特定于 UUIDv6 的更改: 1. 从系统范围的共享稳定存储(例如,文件)或全局变量中,读取 UUID 生成器状态:用于生成最后一个 UUID 的时间戳和时钟序列。 2. 获取自 1582 年 10 月 15 日 00:00:00.00 以来 100 纳秒间隔的 60 位计数的当前时间。 3. 将 time_low 字段设置为起始 60 位时间戳的 12 个最低有效位。 4. 将时间戳截断为 48 个最高有效位以创建 time_high_and_time_mid。 5. 将 time_high 字段设置为截断时间戳的 32 个最高有效位。 6. 将 time_mid 字段设置为截断时间戳的 16 个最低有效位。 Peabody & Davis 于 2021 年 10 月 28 日到期 [第 8 页] Internet-Draft new-uuid-format 2021 年 4 月 7. 通过将 4 位 UUIDv6 版本与 12 位 time_low 连接来创建 16 位 time_low_and_version。 8. 如果状态不可用(例如,不存在或损坏)或时间戳大于当前时间戳,则生成随机的 14 位时钟序列值。 9. 如果状态可用,但保存的时间戳小于或等于当前时间戳,则增加时钟序列值。 10. 通过将时钟序列连接到在 16 位值中占据最重要位置的 UUID 变体位来完成 16 位时钟序列的高、低和保留创建。 11. 生成一个 48 位的伪随机节点。 12. 将每个部分的 128 位连接起来进行格式化:time_high|time_mid|time_low_and_version|variant_clk_seq|node 13. 将状态(当前时间戳和时钟序列)保存回稳定存储 将 time_high_and_time_mid 拆分为 time_high 和 time_mid 的步骤是可选的,因为time_high 和 time_mid 的 48 位将在最终连接期间保持与 time_high_and_time_mid 相同的顺序。在重用现有的 UUIDv1 实现时,这一额外的分割为最高有效 32 位和最低有效 16 位的步骤证明很有用。其中可以应用以下逻辑以最少的修改重新排列位。 +--------------+------+--------------+ | UUIDv1 字段 |位 | UUIDv6 字段 | +--------------+------+--------------+ |时间低 | 32 | time_high | +--------------+------+--------------+ | time_mid | 16 | time_mid | +--------------+------+--------------+ | time_high | 12 |时间低 | +--------------+------+--------------+ 表 3:UUIDv1 到 UUIDv6 字段映射 Peabody & Davis 到期2021 年 10 月 28 日 [第 9 页] Internet-Draft new-uuid-format 2021 年 4 月 4.4。 UUIDv7 布局和位顺序 UUIDv7 格式旨在以任意亚秒级精度对 Unix 时间戳进行编码。 UUIDv7 提供的关键属性是由一个系统生成并由另一个系统解析的时间戳值保证具有生成器或解析器的子部分精度,以较小者为准。此外,解析 UUIDv7 值的系统不需要知道在编码期间使用了哪种精度才能正常运行。 16 字节、128 位 UUIDv6 的格式如图 2 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+-+-+-+-+-+-+-+-+ | unixt | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- +-+-+-+-+-+-+-+ |unixts | subsec_a |版本 | subsec_b | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- +-+-+-+-+-+-+-+ |var|潜艇……