GUID 是否 100% 都是唯一的?
它会在多个线程上保持唯一吗?
虽然不能保证每个生成的 GUID 都是唯一的,但唯一键的总数(2 128或 3.4×10 38)是如此之大,以至于相同数字被生成两次的概率非常小。例如,考虑可观测宇宙,它包含大约 5×10 22 颗恒星;然后,每颗星都可以有 6.8×10 15 个普遍唯一的 GUID。
来自维基百科。
这些是关于如何制作 GUID(对于 .NET)以及如何在正确的情况下获得相同的 guid 的一些好文章。
https://ericlippert.com/2012/04/24/guid-guide-part-one/
https://ericlippert.com/2012/04/30/guid-guide-part-two/
https://ericlippert.com/2012/05/07/guid-guide-part-three/
</p>
如果您害怕相同的 GUID 值,请将它们中的两个并排放置。
Guid.NewGuid().ToString() + Guid.NewGuid().ToString();
如果你太偏执,那就放三个。
简单的答案是肯定的。
Raymond Chen 写了一篇关于 GUID 以及为什么 GUID 的子字符串不能保证唯一的文章。本文深入探讨了 GUID 的生成方式以及它们用于确保唯一性的数据,这应该在一定程度上解释它们的原因:-)
附带说明一下,我在 Windows XP 中使用 Volume GUID。这是一个非常模糊的分区布局,包含三个磁盘和十四个卷。
\\?\Volume{23005604-eb1b-11de-85ba-806d6172696f}\ (F:)
\\?\Volume{23005605-eb1b-11de-85ba-806d6172696f}\ (G:)
\\?\Volume{23005606-eb1b-11de-85ba-806d6172696f}\ (H:)
\\?\Volume{23005607-eb1b-11de-85ba-806d6172696f}\ (J:)
\\?\Volume{23005608-eb1b-11de-85ba-806d6172696f}\ (D:)
\\?\Volume{23005609-eb1b-11de-85ba-806d6172696f}\ (P:)
\\?\Volume{2300560b-eb1b-11de-85ba-806d6172696f}\ (K:)
\\?\Volume{2300560c-eb1b-11de-85ba-806d6172696f}\ (L:)
\\?\Volume{2300560d-eb1b-11de-85ba-806d6172696f}\ (M:)
\\?\Volume{2300560e-eb1b-11de-85ba-806d6172696f}\ (N:)
\\?\Volume{2300560f-eb1b-11de-85ba-806d6172696f}\ (O:)
\\?\Volume{23005610-eb1b-11de-85ba-806d6172696f}\ (E:)
\\?\Volume{23005611-eb1b-11de-85ba-806d6172696f}\ (R:)
| | | | |
| | | | +-- 6f = o
| | | +---- 69 = i
| | +------ 72 = r
| +-------- 61 = a
+---------- 6d = m
并不是 GUID 非常相似,而是所有 GUID 中都包含字符串“mario”这一事实。这是巧合还是背后有解释?
现在,当我在 GUID 中搜索第 4 部分时,我发现大约 125.000 次点击量 GUID。
结论:当涉及到卷 GUID 时,它们并不像其他 GUID 那样独特。
它不应该发生。但是,当 .NET 负载过重时,可能会获得重复的 guid。我有两个不同的 Web 服务器使用两个不同的 sql 服务器。我去合并数据,发现我有 1500 万个向导和 7 个重复项。
是的,GUID 应该始终是唯一的。它基于硬件和时间,加上一些额外的位以确保它是独一无二的。我敢肯定,理论上有可能最终得到两个相同的,但在现实世界中极不可能。
这是 Raymond Chen 关于 Guids 的一篇很棒的文章:
https://blogs.msdn.com/oldnewthing/archive/2008/06/27/8659071.aspx </p>
指南在统计上是唯一的。两个不同客户端生成相同 Guid 的几率非常小(假设 Guid 生成代码中没有错误)。你也可以担心你的处理器由于宇宙射线而出现故障,并决定今天 2+2=5。
分配新 guid 的多个线程将获得唯一值,但您应该知道您正在调用的函数是线程安全的。这是在哪个环境?
Eric Lippert 撰写了一系列非常有趣的关于 GUID 的文章。
世界上大约有 2 30台个人计算机(当然还有很多手持设备或非 PC 计算设备具有或多或少相同水平的计算能力,但让我们忽略这些)。假设我们将世界上所有这些 PC 用于生成 GUID 的任务;如果每个人每秒可以生成 2 20 个GUID,那么仅在大约 2 72秒(150 万亿年)之后,您将很有可能与您的特定 GUID 发生冲突。仅仅 30 万亿年之后,碰撞的几率就变得相当高了。
从理论上讲,不,它们不是唯一的。可以一遍又一遍地生成相同的 guid。然而,它发生的机会是如此之低,以至于你可以假设它们是独一无二的。
我以前读过,机会如此之低,以至于你真的应该强调其他事情——比如你的服务器自发燃烧或代码中的其他错误。也就是说,假设它是独一无二的,并且不构建任何代码来“捕获”重复项——将时间花在更有可能发生的事情上(即其他任何事情)。
我尝试向我的博客读者(非技术家庭成员)描述 GUID 的用处。从那里(通过维基百科),生成重复 GUID 的几率:
似乎没有人提到它发生概率的实际数学。
首先,假设我们可以使用整个 128 位空间(Guid v4 仅使用 122 位)。
我们知道在n
选秀中没有得到重复的一般概率是:
(1-1/2 128 )(1-2/2 128 )...(1-(n-1)/2 128 )
因为 2 128远大于n
,我们可以将其近似为:
(1-1/2 128 ) n(n-1)/2
因为我们可以假设n
它远大于 0,所以我们可以将其近似为:
(1-1/2 128 ) n^2/2
现在我们可以将其等同于“可接受的”概率,比如说 1%:
(1-1/2 128 ) n^2/2 = 0.01
我们解决n
并得到:
n = sqrt(2* log 0.01 / log (1-1/2 128 ))
哪个 Wolfram Alpha 得到5.598318 × 10 19
从这个数字来看,让我们以 10000 台机器为例,每台机器都有一个 4 核 CPU,运行 4Ghz 并花费 10000 个周期来生成一个 Guid,并且什么都不做。然后他们需要大约 111 年才能生成副本。
来自http://www.guidgenerator.com/online-guid-generator.aspx
什么是 GUID?
GUID(或 UUID)是“全局唯一标识符”(或“通用唯一标识符”)的首字母缩写词。它是一个 128 位整数,用于标识资源。GUID 一词通常由使用 Microsoft 技术的开发人员使用,而 UUID 则在其他任何地方使用。
GUID 有多独特?
128 位足够大,生成算法也足够独特,如果在 1 年内每秒生成 1,000,000,000 个 GUID,则重复的概率仅为 50%。或者,如果地球上的每个人都生成了 600,000,000 个 GUID,那么重复的概率只有 50%。
GUID 是否 100% 都是唯一的?
不能保证,因为有几种生成方法。但是,您可以尝试计算创建两个相同 GUID 的机会,然后您就会明白:一个 GUID 有 128 位,因此,有 2 128个不同的 GUID——比已知宇宙中的恒星多得多。阅读维基百科文章了解更多详情。
MSDN:
新 Guid 的值全为零或等于任何其他 Guid 的概率非常低。
如果您的系统时钟设置正确并且没有环绕,并且您的 NIC 有自己的 MAC(即您没有设置自定义 MAC)并且您的 NIC 供应商没有回收 MAC(他们不应该这样做)但已知会发生),并且如果您的系统的 GUID 生成功能正确实现,那么您的系统将永远不会生成重复的 GUID。
如果地球上每个生成 GUID 的人都遵循这些规则,那么您的 GUID 将是全球唯一的。
在实践中,违反规则的人数很少,他们的 GUID 不太可能“逃脱”。冲突在统计上是不可能的。
我遇到了重复的 GUID。
我使用 Neat Receipts 桌面扫描仪,它带有专有的数据库软件。该软件具有同步到云的功能,但我在同步时一直出错。仔细看日志,发现了令人敬畏的一行:
"errors":[{"code":1,"message":"creator_guid: 已被占用","guid":"C83E5734-D77A-4B09-B8C1-9623CAC7B167"}]}
我有点难以置信,但可以肯定的是,当我找到进入我本地的整洁数据库的方法并删除包含该 GUID 的记录时,错误停止发生。
所以用轶事证据回答你的问题,不。可以复制。但它发生的原因很可能不是偶然的,而是由于没有以某种方式遵守标准做法。(我只是没那么幸运)但是,我不能肯定地说。这不是我的软件。
他们的客户支持非常有礼貌和乐于助人,但他们以前一定从未遇到过这个问题,因为在与他们通了 3 个多小时的电话后,他们没有找到解决方案。(FWIW,Neat 给我留下了深刻的印象,这个故障,无论多么令人沮丧,并没有改变我对他们产品的看法。)
为了获得更好的结果,最好的方法是在 GUID 后面加上时间戳(只是为了确保它保持唯一)
Guid.NewGuid().ToString() + DateTime.Now.ToString();
在多线程/多进程单元测试期间,我经历过 GUID 不是唯一的(也是?)。我想这与伪随机生成器的相同播种(或缺少播种)有关,在所有其他情况相同的情况下。我用它来生成唯一的文件名。我发现操作系统在这方面做得更好:)
您询问 GUID 是否 100% 唯一。这取决于它必须是唯一的 GUID 的数量。随着 GUID 的数量接近无穷大,重复 GUID 的概率接近 100%。
在更一般的意义上,这被称为“生日问题”或“生日悖论”。维基百科有一个很好的概述: 维基百科 - 生日问题
粗略地说,池大小的平方根是一个粗略的近似值,即您可以预期 50% 的重复几率。文章包括一个池大小和各种概率的概率表,包括 2^128 的一行。因此,对于 1% 的碰撞概率,您会期望随机选择 2.6*10^18 个 128 位数字。50% 的机会需要 2.2*10^19 次选择,而 SQRT(2^128) 是 1.8*10^19。
当然,这只是真正随机过程的理想情况。正如其他人所提到的,很多东西都依赖于随机方面——生成器和种子到底有多好?如果有一些硬件支持来协助这个过程会很好,这将更加防弹,除了任何东西都可以被欺骗或虚拟化。我怀疑这可能是不再包含 MAC 地址/时间戳的原因。
“GUID 是 100% 唯一的吗?”的答案 只是“不”。
如果您想要 GUID 的 100% 唯一性,请执行以下操作。
GUID 算法通常根据 v4 GUID 规范实现,该规范本质上是一个伪随机字符串。可悲的是,这些属于“可能不唯一”的类别,来自维基百科(我不知道为什么这么多人忽略这一点):“......其他 GUID 版本具有不同的唯一性属性和概率,范围从保证唯一性到可能的非唯一性。”
V8 的 JavaScript 的伪随机属性Math.random()
在唯一性方面非常糟糕,碰撞通常在几千次迭代后发生,但 V8 并不是唯一的罪魁祸首。我已经看到使用 v4 GUID 的 PHP 和 Ruby 实现的真实 GUID 冲突。
因为跨多个客户端和服务器集群扩展 ID 生成变得越来越普遍,熵受到了很大的打击——相同的随机种子被用于生成 ID 升级的机会(时间通常被用作随机种子在伪随机生成器中),并且 GUID 冲突从“可能不唯一”升级为“很可能造成很多麻烦”。
为了解决这个问题,我着手创建一个可以安全扩展的 ID 算法,并更好地保证防止碰撞。它通过使用时间戳、内存中的客户端计数器、客户端指纹和随机字符来实现。各种因素的组合产生了一种特别抗碰撞的附加复杂性,即使您在多个主机上扩展它:
最困难的部分不是生成重复的 Guid。
最难的部分是设计一个数据库来存储所有生成的数据库,以检查它是否真的重复。
来自维基:
例如,为了有 50% 的概率至少发生一次冲突,需要生成的随机版本 4 UUID 的数量为 2.71 quintillion,计算如下:
这个数字相当于每秒生成 10 亿个 UUID 大约 85 年,一个包含这么多 UUID 的文件(每个 UUID 16 个字节)大约是 45 艾字节,比目前存在的最大数据库大很多倍,数百 PB 的数量级
GUID 代表全球唯一标识符
简而言之:(线索就在名字里)
详细说明:GUID 的设计是独一无二的;它们是使用基于计算机时钟和计算机本身的随机方法计算的,如果您在同一台机器上以相同的毫秒时间创建多个 GUID,它们可能会匹配,但对于几乎所有正常操作,它们应该被认为是唯一的。
足够的 GUID 可以为可见宇宙中每颗恒星周围的每个假设行星上的每个假设沙粒分配一个。
足以让如果世界上每台计算机在 200 年内每秒生成 1000 个 GUID,则可能(可能)会发生碰撞。
考虑到 GUID 的当前本地使用数量(例如,每个数据库每个表一个序列),对于我们有限的生物(以及寿命通常不到 10 年,如果不是一两年的机器)来说,这极不可能成为问题用于手机)。
...我们现在可以关闭这个线程吗?
我认为,当人们将自己的想法和恐惧隐藏在统计数据中时,他们往往会忘记显而易见的事情。如果一个系统确实是随机的,那么您最不可能期望的结果(例如全为 1)与任何其他意外值(例如全零)的可能性相同。这两个事实都不能阻止这些连续发生,也不能在第一对样本中发生(即使这在统计上是“真正令人震惊的”)。这就是衡量机会的问题:它完全忽略了关键性(和坏运气)。
如果曾经发生过,结果是什么?你的软件停止工作了吗?有人受伤吗?有人死吗?世界会爆炸吗?
临界性越极端,“概率”这个词在口中的表现就越糟糕。最后,当您(主观地)认为您的特定关键性(以及您的“幸运”感觉)不可接受时,链接 GUID(或对它们进行异或,或其他)是您所做的。如果它可以终结世界,那么请代表我们所有未参与大型强子对撞机核实验的人,不要使用 GUID 或其他任何不确定的东西!