代码之家  ›  专栏  ›  技术社区  ›  Diego Jancic

使用不同算法的UUID碰撞风险

  •  17
  • Diego Jancic  · 技术社区  · 14 年前

    我有一个数据库,其中2个(或者3个或4个)不同的应用程序正在插入信息。新信息的ID类型为guid/uuid,但每个应用程序使用不同的算法生成ID。例如,一个使用nhibernate的“guid.comb”,另一个使用sqlserver的newid(),另一个可能需要使用.net的guid.newguid()实现。

    是否存在ID冲突或重复的高于正常水平的风险?

    谢谢!

    2 回复  |  直到 13 年前
        1
  •  22
  •   Community M-A    7 年前

    碰撞的风险略有上升,但仍然很小。认为:

    • 梳齿和 NEWID / NEWSEQUENTIALID 包括一个精确到几毫秒的时间戳 阿西 . 因此,除非在 完全相同的时刻 从所有这些不同的来源,它确实是 不可能的 让ID发生冲突。

    • guid的一部分 不是 基于时间戳可以被认为是随机的;大多数guid算法基于prng。因此,其他10个字节之间发生冲突的可能性与使用两个独立的随机数生成器并观察冲突的顺序相同。

      想一想这一点——prng可以并且可以重复数字,所以它们之间发生碰撞的可能性并不比只使用其中一个的碰撞高很多,即使它们使用的算法稍有不同。这有点像是每周玩相同的彩票号码,而不是每周随机挑选一组彩票号码——两种方法中获胜的几率完全相同。

    现在,请记住,当您使用guid.comb之类的算法时,您只有10位uniqueifier,相当于1024个单独的值。因此,如果在相同的几毫秒内生成大量的guid,那么 发生碰撞。但是,如果您以相当低的频率生成guid,那么在同一时间使用多少不同的算法并不重要,冲突的可能性实际上仍然不存在。

    最好的方法是运行一个测试;让所有2个或3个(或者不管你使用了多少个)生成guid,同时以固定的时间间隔,并将它们写到一个日志文件中,看看是否会发生冲突(如果是,有多少)。这应该能让你很好地了解这在实践中的安全性。

    另外,如果您正在使用nhibernate的梳状生成器为集群主键生成guid,请考虑使用 NEWSEQUENTIALID() 而不是 NEWID() -梳子的关键是避免页面分割,如果您有其他使用非顺序算法的进程,那么您就无法实现这一点。您还应该使用 Guid.NewGuid 使用相同的梳状发生器-实际使用的梳状算法是 not complicated 在您自己的域逻辑中很容易复制。

    _ 尼维德 以及是否包含时间戳。在任何情况下,因为它是基于MAC地址的,所以可能的值的范围远远小于v4 guid或梳。我建议在数据库外使用梳状guid的进一步原因是 新序列 在数据库中。

        2
  •  4
  •   Stephen Cleary    14 年前

    是的,风险高于正常值,因为所有这些都使用不同的“guid.”guid.newguid()定义,它主要是一个符合RFC的随机guid,但newSequentialid是一个基于MAC地址和时间戳的重新排序(因此不符合RFC)guid,而nhibernate的comb guid则完全不同(基于随机性和时间戳)。

    您可能需要考虑只对一个guid实现进行标准化。我对所有应用程序使用自己类型的组合式GUID。 My blog 有所有这些类型的guid的简要描述,以及我自己的设计决策。