【问题标题】:Is a GUID unique 100% of the time?GUID 是否 100% 都是唯一的?
【发布时间】:2010-09-07 13:47:20
【问题描述】:

GUID 是否 100% 都是唯一的?

它会在多个线程中保持唯一吗?

【问题讨论】:

  • 不,不是 100%... 只是 99,999999999999999999999999999999999999999999999999999999999999999999999999999999% ;)
  • 首先,GUID 不是无限的,这意味着对于“100% 的时间”的字面意思,这意味着无论您持续生成 GUID 多久,它们始终是独特。不是这种情况。此外,由于原始实现中不再使用网卡唯一序列号/id/MAC 来生成密钥的一部分,因此由于各种原因,GUID 并不是真正全局唯一更多的。但是,它是本地唯一的。换句话说,如果您继续在一台机器上生成 GUID,您将不会得到重复。
  • @ojrac 我只是选择四舍五入...:P
  • 每次生成 GUID 时,我都觉得自己在从宇宙中偷走一个。有时我会想到邪恶的人,他们生成的 GUID 比他们需要的多得多,而那些浪费掉的 GUID 是如此孤独,不再被使用或生成......
  • @asavartsov 我想你会喜欢wasteaguid.info ^_^

标签: language-agnostic guid


【解决方案1】:

虽然每个生成的 GUID 不是 保证唯一,总 唯一键的数量(2128 或 3.4×1038) 如此之大,以至于相同数字出现的概率 生成两次非常小。为了 例如,考虑可观察的 宇宙,包含大约 5×1022 星星;每个明星都可以拥有 6.8×1015 个普遍唯一的 GUID。

来自Wikipedia


这些是关于如何制作 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/

​​​​

【讨论】:

  • 那它们不应该被称为 UUID 吗? ;)
  • GUID 是微软对 UUID 标准的具体实现。所以,两者兼而有之。全球唯一 ID 与全球唯一 ID。
  • 从技术上讲,它不是 2^128,因为在 v4 GUID 中,您有一个始终为 4 的十六进制数字(实际上删除了 4 位),并且还保留了进一步的两位。但是,2^122 个有效的 V4 GUID 仍然会留下大约 5x10^36,这对我有用。也为你。每颗星星只能接受大约 1.1x10^14 个 GUID。
  • 如果你和我一样,那么你会想知道写出的2^128 大约是:34,028,236,692,093,846,346,337,460,743,177,000,000。从统计上看,如果你每秒计算 1000 个 GUID,仍然需要数万亿年才能得到一个副本。
  • 我只是觉得读出来很有趣,所以在这里玩得开心:) 三十四十亿二十八十亿二百三十六十亿六百九十二亿九十三亿八百四十六亿万三百四十六 quintillion 3337 466 704 430 17700 万
【解决方案2】:

如果您害怕相同的 GUID 值,请将它们中的两个并排放置。

Guid.NewGuid().ToString() + Guid.NewGuid().ToString();

如果你太偏执,那就放三个。

【讨论】:

  • 你必须非常、非常、非常、非常偏执才能附加 3 个 GUID。
  • @harsimranb 不...非常、非常、非常、非常偏执的是 6 个 GUID。偏执是一个附加,非常偏执是两个附加,等等。
  • @Suamere 我创建了一个网站来计算你的偏执程度jogge.github.io/HowParanoidAmI
  • @Jogge xD 太棒了,哈哈。在您的表单中出现 9 9 的 999999999 之后,我认为 Paranoia 会破坏我的浏览器。
  • @Jogge 在我说我是 10,000 级偏执狂之后,您的网站崩溃了。现在我更加偏执了
【解决方案3】:

简单的答案是肯定的。

Raymond Chen 写了一篇关于 GUID 的 great article 以及为什么 GUID 的子字符串保证唯一。本文深入探讨了 GUID 的生成方式以及它们用于确保唯一性的数据,在解释它们的原因时应该花一些时间:-)

【讨论】:

【解决方案4】:

顺便说一句,我在 Windows XP 中使用 Volume GUID。这是一个非常模糊的分区布局,包含 3 个磁盘和 14 个卷。

\\?\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”。这是巧合还是背后有什么解释?

现在,当 googling for part 4 在 GUID 中时,我发现大约 125.000 次点击量 GUID。

结论:就卷 GUID 而言,它们不像其他 GUID 那样独特。

【讨论】:

  • 还记得 80 年代的超级马里奥兄弟 3 广告吗?所有这些人都在大喊“马里奥!马里奥!马里奥!”环游世界有点扰乱宇宙的随机性。
  • 如果您使用msiexec 手动卸载 Office 2010,它会列出该 Office 程序的所有 MSI GUID。他们都拼写0FF1CE。似乎微软对如何生成 GUID 有一个相当……松散的解释;)
  • 这些分区 GUID 都是在 2009-12-17 @ 2:47:45 PM UTC 一起创建的。它们对您的机器来说是唯一的,但是将“mario”作为节点标识符是不正确的——这意味着它们不符合 RFC-4122。同样,0FF1CE GUID 属于 RFC-4122 的“NCS 向后兼容性”部分,但 Microsoft 不太可能遵循这些值的 NCS 规则。
  • 我知道,任天堂安全管理局已经破坏了随机数生成器。
  • 也许这与生产矿泉水的公司名称相同(听说他们引领市场)依云。向后拼写会天真:-)
【解决方案5】:

这不应该发生。但是,当 .NET 负载过重时,可能会获得重复的 guid。我有两个不同的 Web 服务器使用两个不同的 sql 服务器。我去合并数据,发现我有 1500 万个 guid 和 7 个重复项。

【讨论】:

  • 这仅适用于在 GUID 生成过程中使用 MAC 地址(而非机器名称)的 v1 guid。 v4 是事实上的 STD,不再使用 Mac 地址,而是使用伪随机数。
  • Guid.NewGuid 始终生成 v4 GUID(并且始终具有)。蒂姆的熵源一定很差。
  • 有没有被复制过?如果是这样的话,那就是个大问题了。
  • 在导入非常大的数据集时相同。从大约 10 到 1 亿,您从 Guid.NewGuid 获得重复
  • @StephanBaltzer 不,that’s simply impossible。如果这确实发生在您身上,那么您的代码中可能存在错误,例如截断的 GUID 或混淆的数据行。事实上,NewGuid 实现 中存在错误的可能性要大于您真正观察到没有错误的碰撞。但到目前为止,还没有报告过这样的错误,所以我敢打赌,这个问题是在你的代码中。
【解决方案6】:

是的,GUID 应该始终是唯一的。它基于硬件和时间,加上一些额外的位以确保它是独一无二的。我敢肯定,理论上有可能最终得到两个相同的,但在现实世界中极不可能。

这是 Raymond Chen 关于 Guids 的一篇很棒的文章:

https://blogs.msdn.com/oldnewthing/archive/2008/06/27/8659071.aspx ​​​ ​​​ ​

【讨论】:

【解决方案7】:

Guid 在统计上是唯一的。两个不同客户端生成相同 Guid 的几率非常小(假设 Guid 生成代码中没有错误)。您不妨担心您的处理器会因宇宙射线而出现故障,并决定今天 2+2=5。

分配新 guid 的多个线程将获得唯一值,但您应该知道您正在调用的函数是线程安全的。这是在哪个环境中?

【讨论】:

  • 取决于您根据规格使用的 guid 版本。一些指南是基于时间和 MAC 地址的。对于 V2 来说,guid 必须在同一台机器上以相同的皮秒生成。这就像将一袋 1000 美分硬币抛向空中,然后它们全都朝上落到一边,堆成一堆。除非生命受到威胁,否则有可能但不太可能将其视为风险。
【解决方案8】:

Eric Lippert 撰写了一系列非常有趣的关于 GUID 的文章。

世界上有大约 230 台个人电脑(以及 当然有很多手持设备或非 PC 计算设备 或多或少相同水平的计算能力,但让我们忽略 那些)。假设我们将世界上所有这些 PC 放到 生成 GUID 的任务;如果每个人都可以生成,比如说,220 个 GUID 秒,然后大约 272 秒 -- 150 万亿年——你将有非常高的机会产生一个 与您的特定 GUID 发生冲突。碰撞的几率得到 仅仅过了三十万亿年就很好了。

【讨论】:

  • ...他在下一段继续:“但这是在寻找与特定 GUID 的冲突。[...] 所以如果我们让这十亿台 PC 工作,生成 122 -bits-of-randomness GUID,在生成大约 2^61 个 GUID 后,其中两个在某处发生碰撞的概率变得非常高。因为我们假设大约 2^30 台机器每秒执行 2^20 个 GUID ,我们预计会在大约 2^11 秒后发生碰撞,也就是大约一个小时。”(最后他解释说,当然,生成的 GUID 并不多。)
【解决方案9】:

理论上,不,它们不是唯一的。可以一遍又一遍地生成相同的 guid。但是,它发生的可能性非常低,您可以假设它们是独一无二的。

我之前读到过这种可能性非常低,以至于您真的应该对其他事情感到压力 - 例如您的服务器自发燃烧或代码中的其他错误。也就是说,假设它是独一无二的,并且不构建任何代码来“捕获”重复项——把时间花在更有可能发生的事情上(即 任何事情其他)。

made an attempt 向我的博客受众(非技术家庭成员)描述 GUID 的用处。从那里(通过维基百科),生成重复 GUID 的几率:

  • 1 分 2^128
  • 1 in 340 undecillion(别担心,undecillion 不在 测验)
  • 1 英寸 3.4 × 10^38
  • 340,000,000,000,000,000,000,000,000,000,000,000,000 分之一

【讨论】:

  • 实际上,我不同意“不用担心”,尽管立场不同:如果您确实检测到 GUID 冲突,那么您的应用程序出现了问题。例如,我使用 GUID 来实现幂等性,并且在两次发送命令时发生冲突(使用相同的 GUID)。
【解决方案10】:

似乎没有人提到它发生概率的实际数学。

首先,假设我们可以使用整个 128 位空间(Guid v4 仅使用 122 位)。

我们知道在n 选择中没有得到重复的一般概率是:

(1-1/2128)(1-2/2128)...(1-(n-1)/2128 )

因为 2128 远大于 n,我们可以将其近似为:

(1-1/2128)n(n-1)/2

因为我们可以假设n 远大于 0,我们可以将其近似为:

(1-1/2128)n^2/2

现在我们可以将其等同于“可接受”的概率,比如 1%:

(1-1/2128)n^2/2 = 0.01

我们求解n 并得到:

n = sqrt(2* log 0.01 / log (1-1/2128))

Wolfram Alpha 将变为 5.598318 × 1019

从这个数字的角度来看,让我们以 10000 台机器为例,每台机器都有一个 4 核 CPU,运行 4Ghz 并花费 10000 个周期来生成一个 Guid,并且什么都不做。然后,它们需要大约 111 年才能生成副本。

【讨论】:

  • 我已将您的帖子编辑为this post - 如果我做错了请编辑;)。
  • 嗨@Cine,我有权编辑你的回复,但我选择不这样做,因为我想有机会让你先反驳它,我可能会在一个月后过来如果我没有收到您的来信,就正式更改它。我相当肯定你的数学是错误的。确定 1% 机会的真正方程式是:((2^128 - 1) / 2 ^128) ^ ( (n (n-1)) / 2) = .01。你的指数是错误的。它不只是 n。当您生成“n”个向导时,您需要 C(n,2)(又名 (n*(n-1))/2) 来计算所有组合。请参阅此处了解更多信息
  • 感谢 Cine,我最终也接近 n^2/2,因为它是如此之大 :)
  • 10000 台机器需要 111 年才能生成每个可能的 GUID,然后生成一个副本。然而,在所有可能的 GUID 生成之前很久就会发生重复。我认为大概的时间范围取决于 GUID 生成过程的“随机”程度。
  • @GeorgeK 我想你误解了...... 10000 台机器需要 111 年才能有 1% 的机会遇到重复。但是,是的,这个数学当然假设随机生成器是完全随机的。
【解决方案11】:

来自http://www.guidgenerator.com/online-guid-generator.aspx

什么是 GUID?

GUID(或 UUID)是“Globally Unique Identifier”(或“Universally Unique Identifier”)的首字母缩写词。它是一个 128 位整数,用于标识资源。 GUID 一词通常由使用 Microsoft 技术的开发人员使用,而 UUID 则用于其他任何地方。

GUID 的独特性如何?

128 位足够大,生成算法也足够独特,如果在 1 年内每秒生成 1,000,000,000 个 GUID,则重复的概率仅为 50%。或者,如果地球上的每个人都生成了 600,000,000 个 GUID,那么重复的概率只有 50%。

【讨论】:

  • 50% 的重复几率不是高到足以引起恐惧吗?
  • @disklosr 是的,如果您的系统每秒生成 10 亿个 GUID,这足以引起恐惧。在极不可能的情况下,您生成该数量然后只需将两个 GUID 链接在一起......
【解决方案12】:

GUID 是否 100% 都是唯一的?

不保证,因为有几种方法可以生成一个。但是,您可以尝试计算创建两个相同 GUID 的机会,然后您就会明白:一个 GUID 有 128 位,因此,有 2128 个不同的 GUID - 很多 比已知宇宙中的星星还要多。阅读wikipedia article了解更多详情。

【讨论】:

    【解决方案13】:

    MSDN

    新 Guid 的值全为零或等于任何其他 Guid 的概率非常低。

    【讨论】:

      【解决方案14】:

      如果您的系统时钟设置正确并且没有回绕,并且您的 NIC 有自己的 MAC(即您没有设置自定义 MAC)并且您的 NIC 供应商没有回收 MAC(它们不是应该做但已知会发生),并且如果您的系统的 GUID 生成功能正确实现,那么您的系统将永远不会生成重复的 GUID。

      如果地球上每个生成 GUID 的人都遵循这些规则,那么您的 GUID 将是全球唯一的。

      在实践中,违反规则的人数很少,他们的 GUID 不太可能“逃脱”。冲突在统计上是不可能的。

      【讨论】:

      • 这仅适用于 v1 guid。 v4 是事实上的 STD,不再使用 Mac 地址,而是使用伪随机数。
      • "那么您的系统将永远不会生成重复的 GUID" 即使您所说的 v1 guid 遵循了所有规则,您的系统仍然可以生成重复的 GUID。当您说“冲突在统计上是不可能的”时,您在底部更正确。
      【解决方案15】:

      我遇到了重复的 GUID。

      我使用 Neat Receipts 桌面扫描仪,它带有专有的数据库软件。该软件具有同步到云的功能,但我在同步时一直出错。仔细一看日志,发现了很棒的一行:

      "errors":[{"code":1,"message":"creator_guid: 已经是 采取","guid":"C83E5734-D77A-4B09-B8C1-9623CAC7B167"}]}

      我有点不敢相信,但可以肯定的是,当我找到进入本地neaworks 数据库的方法并删除包含该 GUID 的记录时,错误停止发生。

      所以用轶事证据回答你的问题,不。可以复制。但它发生的原因很可能不是偶然的,而是由于没有以某种方式遵守标准做法。 (我只是没那么幸运)但是,我不能肯定地说。这不是我的软件。

      他们的客户支持非常有礼貌和乐于助人,但他们之前一定从未遇到过这个问题,因为在与他们通了 3 个多小时的电话后,他们没有找到解决方案。 (FWIW,Neat 给我留下了深刻的印象,这个故障,无论多么令人沮丧,并没有改变我对他们产品的看法。)

      【讨论】:

      • 不要相信你有重复。可能还涉及其他一些问题,例如数字不是真正随机的或同步过程中的问题,或者系统尝试记录两次等。软件问题比您获得重复 GUID 的可能性要大得多。
      【解决方案16】:

      为了获得更好的结果,最好的方法是在 GUID 后面加上时间戳(只是为了确保它保持唯一)

      Guid.NewGuid().ToString() + DateTime.Now.ToString();
      

      【讨论】:

      • 如果在同一秒内发生两次碰撞怎么办?
      • 这是最坏的情况,但我们不能同时生成相同的两个 Guid。
      • 他们在某个地方争辩说,应该从 SO 的答案中复制,而不是问题,但我现在不太确定......
      • Guid.NewGuid().ToString().Replace("-", "") + DateTime.Now.Ticks....键
      【解决方案17】:

      我在多线程/多进程单元测试期间体验过 GUID 不是唯一的(也是?)。我想这与伪随机生成器的相同播种(或缺少播种)有关,在所有其他条件相同的情况下。我用它来生成唯一的文件名。我发现操作系统在这方面做得更好:)

      拖钓警报

      您询问 GUID 是否 100% 唯一。这取决于它必须是唯一的 GUID 的数量。随着 GUID 的数量接近无穷大,重复 GUID 的概率接近 100%。

      【讨论】:

        【解决方案18】:

        在更一般的意义上,这被称为“生日问题”或“生日悖论”。维基百科在以下方面有一个很好的概述: Wikipedia - Birthday Problem

        在非常粗略的情况下,池大小的平方根是一个粗略的近似值,即您可以预期 50% 的重复几率。文章包括一个池大小和各种概率的概率表,包括 2^128 的一行。因此,对于 1% 的碰撞概率,您会期望随机选择 2.6*10^18 个 128 位数字。 50% 的机会需要 2.2*10^19 次选择,而 SQRT(2^128) 是 1.8*10^19。

        当然,这只是真正随机过程的理想情况。正如其他人提到的那样,随机方面有很多东西 - 生成器和种子有多好?如果有一些硬件支持来协助这个过程会很好,这将更加防弹,除了任何东西都可以被欺骗或虚拟化。我怀疑这可能是不再包含 MAC 地址/时间戳的原因。

        【讨论】:

        • 我认为 MAC 问题是匿名性。我相信以一种可以逆转的方式使用诸如 MAC 地址之类的标识符是一个隐私问题。我相信硬件中的真正随机非常困难? Cloudflare 使用了一个摄像头和一排熔岩灯,但是我认为如果对物理学有精确的理解,即使这样也不是随机的? Cloudflares 熔岩灯 RNG:popularmechanics.com/technology/security/news/a28921/…
        【解决方案19】:

        “一个 GUID 是 100% 唯一的吗?” 的答案只是 “否”

        • 如果您想要 GUID 的 100% 唯一性,请执行以下操作。

          1. 生成 GUID
          2. 检查该 GUID 是否存在于您正在寻找唯一性的表列中
          3. 如果存在则转到第 1 步,否则转到第 4 步
          4. 将此 GUID 用作唯一的。

        【讨论】:

        • 这并不意味着它是独一无二的。您的算法不会将新创建的 GUID 保存在表中。下次创建 GUID 时,它可能会与之前的 GUID 发生冲突。如果您要将 GUID 插入到表中,则 GUID 可能已经被另一个对等方插入,在您检查唯一性并将 GUID 插入到表中之间。 GUID 仅在您的系统中是唯一的,因此如果您要导入或合并两个数据库,它们仍然可能发生冲突。当您无权访问中心化数据库时,也经常使用 GUID。如果你有,为什么不从数据库中提取一个 ID?
        【解决方案20】:

        GUID 算法通常根据 v4 GUID 规范实现,该规范本质上是一个伪随机字符串。可悲的是,这些属于 “可能不唯一” 的类别,来自 Wikipedia(我不知道为什么这么多人忽略这一点):“......其他 GUID 版本具有不同的唯一性属性和概率,范围从保证的唯一性到可能的非唯一性。”

        V8 的 JavaScript Math.random() 的伪随机属性在唯一性方面非常糟糕,碰撞通常仅在几千次迭代后发生,但 V8 并不是唯一的罪魁祸首。我已经看到使用 v4 GUID 的 PHP 和 Ruby 实现的真实 GUID 冲突。

        由于跨多个客户端和服务器集群扩展 ID 生成变得越来越普遍,因此熵受到了很大的影响——相同的随机种子被用于生成 ID 升级的机会(时间通常被用作伪随机生成器中的随机种子),并且 GUID 冲突从“可能不唯一”升级为“很可能造成很多麻烦”。

        为了解决这个问题,我着手创建一种可以安全扩展的 ID 算法,并更好地保证不会发生冲突。它通过使用时间戳、内存中的客户端计数器、客户端指纹和随机字符来实现。多种因素的组合产生了一种特别抗碰撞的附加复杂性,即使您将其扩展到多个主机:

        http://usecuid.org/

        【讨论】:

          【解决方案21】:

          最难的部分不是生成重复的 Guid。

          最难的部分是设计一个数据库来存储所有生成的数据以检查它是否真的重复。

          来自维基:

          例如,为了有 50% 的概率至少发生一次冲突,需要生成的随机版本 4 UUID 的数量为 2.71 quintillion,计算如下:

          enter image description here

          这个数字相当于每秒生成 10 亿个 UUID 大约 85 年,而包含这么多 UUID 的文件(每个 UUID 16 个字节)大约为 45 艾字节,比目前存在的最大数据库大很多倍,大约是数百 PB

          【讨论】:

            【解决方案22】:

            GUID 代表全局唯一标识符

            简介: (线索就在名字里)

            详细说明: GUID 的设计是独一无二的;它们是使用基于计算机时钟和计算机​​本身的随机方法计算的,如果您在同一台机器上以相同的毫秒数创建多个 GUID,它们可能会匹配,但对于几乎所有正常操作,它们应该被认为是唯一的。

            【讨论】:

              【解决方案23】:

              足够的 GUID 可以为可见宇宙中每颗恒星周围的每个假设行星上的每个假设沙粒分配一个。

              如果世界上每台计算机在 200 年内每秒生成 1000 个 GUID,就可能(可能)发生碰撞。

              鉴于 GUID 当前在本地使用的数量(例如,每个数据库每个表一个序列),对于我们有限的生物(以及寿命通常不到十年的机器,如果不是手机一两年)。

              ...我们现在可以关闭这个帖子吗?

              【讨论】:

                【解决方案24】:

                我认为,当人们将自己的想法和恐惧隐藏在统计数据中时,他们往往会忘记显而易见的事情。如果一个系统确实是随机的,那么您最不可能期望的结果(例如全为 1)与任何其他意外值(例如全零)一样可能。这两个事实都不能阻止这些连续发生,也不能在第一对样本中发生(即使这在统计上是“真正令人震惊的”)。这就是衡量机会的问题:它完全忽略了关键性(和坏运气)。

                如果曾经发生过,结果如何?你的软件停止工作了吗?有人受伤吗?有人死吗?世界会爆炸吗?

                临界性越极端,“概率”这个词在口中的表现就越糟糕。最后,当您(主观地)认为您的特定关键性(以及您的“幸运”感觉)不可接受时,链接 GUID(或对它们进行异或,或其他)是您所做的。如果它可以终结世界,那么请代表我们所有未参与大型强子对撞机核实验的人,不要使用 GUID 或其他任何不确定的东西!

                【讨论】:

                  猜你喜欢
                  • 2010-09-13
                  • 2011-02-27
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-11-17
                  • 2018-03-25
                  • 1970-01-01
                  • 2013-08-20
                  相关资源
                  最近更新 更多