如何创建我自己的具有较小 "global" 的 GUID 算法?

How can I create my own GUID algorithm with smaller "global"?

我有自己的应用程序 "global" 比我们真正的全局要小得多,我想要更短的 GUID 版本。现在假设我有我估计永远不会超过的 ID 的具体数量(例如 1 亿个 ID)。如何确定与 GUID 具有相同 属性 所需的随机位数? (全球唯一,无需中央权威机构生成)使用普通的 GUID 就太过分了。

我的 "overkill" 指的是:我需要 ID 尽可能容易地 typed/say/write 向下并且同时具有与 GUID 一样低的天文数字碰撞机会。听说GUID可以分配给地球上的每一粒沙子。我的应用是一个游戏,每个玩家生成一个ID,显然我的玩家还没有地球上的沙子多。

玩家要是能说"My ID is XXXX-XXXX"就最好了。在那种情况下,我不太确定 8 个随机十六进制字符对于 1 亿玩家来说是不够还是太多。 (实际上我将它编码为 A-Z 0-9 而不是十六进制)我的游戏不受在线限制,所以我希望每个玩家即使不在线也能获得唯一的 ID。 (没有检查 ID 冲突的服务器)

GUID 被设计为全局唯一。但我不知道为什么会产生 128 位序列。也许他们只是选择 "very large" 那个是 2 的幂?不知道他们在设计GUID的时候是怎么想的,保证不会冲突。 (他们用世界人口倍数?如果是这样我也可以用1000万倍。)

128 位 guid 通常会表现良好,因为大多数编译器足够聪明,可以将对其的操作减少为一对 64 位操作(在某些 CPU 上,一个 128 位扩展操作)。 Java 和 C#/VB.NET 可能比 C++ 有更多的开销,但是如果你使用 Java 或 C#/VB.NET,你已经接受了很多多一点开销,GUID 不会增加太多。

但是,如果您确实需要更小的值,您可以手动减少 GUID,方法是对高 64 位与低 64 位进行异或运算(从而保留 一些 的唯一性原始的)来创建一个紧凑的 64 位大部分唯一的数字。

您可以用类似的方式减少到 32 位或 48 位,总是原始 GUID 大小的倍数。这样做的好处是,您可以从一个旨在在非常大的集合中保持唯一的数字开始。但是,请记住,1 亿个项目需要相当多的位数来保持非重叠保证,因此如果您不小心,稍后可能会遇到一个非常难以发现的问题。

一种粗略但可能同样有效的方法是使用密码安全的随机数生成器并构造一个与您需要一样大的数字(可能最小为 48 位)。重要的是不要对结果进行模运算,否则会显着降低唯一性(由于随机数生成器的周期)。

我假设您不能使用顺序 ID,尽管您可能想重新考虑这个想法并看看是否有办法使顺序 ID 起作用。例如,您可以使用与随机种子数配对的顺序 ID,保证唯一性而不需要大量数据,并允许内部索引操作和大型数据集常见的类似优化。

好的,我和朋友商量过,想出了解决办法。我的游戏ID的"characters"个数是这样决定的

一个字符将由0-9和A-Z组成,而不是HEX,即36种字符。我们去掉了 0 O 1 I 这样它就可以打印成各种字体而不会混淆,剩下 32 种字符。

那么如果每个角色都被伪随机化,我们可以安全地拥有多少玩家?

我们使用了 Birthday paradox 的平方近似。该页面中的公式表明需要多少人才能有 50% 的几率发生 2 人碰撞。生日问题是22.99人。 (365 种可能的选择)

现在我们将 32^No.of 个字符代替 365 个字符代入等式。这是多少玩家将导致 2 个玩家具有相同 ID 的概率为 50% :

最后,我们同意选择 9 个字符的 ID,这样游戏最多可以注册 690 万玩家,然后所有 690 万玩家中只有 2 个拥有相同的 ID(50% 的几率)。

该游戏甚至不是在线游戏!只有当这 2 名玩家仍在同一时间积极比赛并决定在同一周将分数发送到记分板时才会发生碰撞,因为每周分数重置。所以游戏实际可以容纳的数量会比这高一些。 (这款游戏应该不会有那么多玩家。。这只是每个游戏初创公司的一个小小的幸福梦想。好吧至少计算很有趣。)

为了便于阅读,它可能看起来像这样:5XT-339-A67