首页 > 解决方案 > 更改 GUID 中的两个字节

问题描述

我正在使用分区 CosmosDb,但每次我想通过其 id 获取资源时,我都不知道分区键的值。现在使用 id 作为分区键对我来说不是一个解决方案,因为它会花费太长时间并且占用太多空间(我听说分区键的最大数量是 10GB,但我有更多。)

我的想法是操纵 2 个字节的 GUID,以便将我的分区键值映射到每个 guid。这样我就不必使用跨分区查询,而是轻松地从我的 GUID 中获取分区键值。GUID 中是否有任何我无法更改的保留字节?这个问题有什么最佳实践吗?

标签: c#azure-cosmosdbguiddata-partitioning

解决方案


GUID 中有一个基于时间的组件,您可以更改它,如果您了解后果,就不会导致冲突。你可以在这里阅读一些想法:

https://blog.stephencleary.com/2010/11/few-words-on-guids.html

相关部分内容如下:

基于时间的 GUID(版本 1) 基于时间的 GUID 是变体 2,版本 1 RFC 4122 GUID,也称为“顺序 GUID”,因为它们可以使用彼此非常接近的值生成。除了 Variant 和 Version 之外,它们还包含三个字段:60 位 UTC 时间戳、14 位时钟序列和 48 位节点标识符。

节点标识符通常是生成基于时间的 GUID 的计算机的 MAC 地址(保证是唯一的,因为 MAC 地址使用注册系统)。但是,它也可能是一个 47 位随机值(设置了广播位)。在这种情况下,不存在与真实 MAC 地址发生冲突的危险,因为物理 MAC 地址的广播位始终为 0。但是,存在与其他随机节点标识符发生冲突的危险;具体来说,一旦有 1397 万个随机节点进入网络,就有 50% 的机会发生碰撞。

注意:微软的 Win32 API 目前不支持使用随机值代替 MAC 地址。这意味着使用 UuidCreateSequential 完成的任何 GUID 生成都将公开 MAC 地址。

时钟序列字段被初始化为一个随机值,并在系统时钟自上次生成 GUID 后向后移动时递增(例如,如果计算机使用时间服务器更正其时间,或者如果它丢失了日期并认为它是 1980 年)。这允许 16,384 次时钟复位而没有任何冲突的危险。如果 GUID 生成得如此之快以至于系统时钟自上一个 GUID 的时间戳以来没有向前移动,则 GUID 生成算法通常会停止,直到系统时钟增加时间戳。

顺序 GUID 实际上不是顺序的。在正常情况下,由同一台计算机生成的 GUID 将具有逐渐增加的时间戳字段(其他字段保持不变)。但是,时间戳字段不在 GUID 的最低有效位位置,因此如果将 GUID 视为 128 位数字,它实际上不会递增。

请务必注意,顺序 GUID 发生冲突的可能性非常小。时钟序列和时间戳几乎可以肯定唯一地标识一个时间点,而节点标识符几乎可以肯定地标识一个唯一源。

可以通过 Win32 函数 UuidCreateSequential 或使用 Windows SDK 中的 uuidgen.exe 传递 -x 参数来创建顺序 GUID。

您还可以在此处查看相关规范:

https://www.rfc-editor.org/rfc/rfc4122#section-4.1.1


推荐阅读