我有一个数据库,其中2个(或可能是3或4个)不同的应用程序正在插入信息。新信息具有GUID / UUID类型的ID,但每个应用程序使用不同的算法来生成ID。例如,一个使用NHibernate的“guid.comb”,另一个使用SQLServer的NEWID(),其他人可能想使用.NET的Guid.NewGuid()实现。
是否存在ID碰撞或重复的正常风险?
谢谢!
答案 0 :(得分:22)
碰撞的风险略有提升,但仍然很小。考虑一下:
Comb和NEWID
/ NEWSEQUENTIALID
都包含精度低至几毫秒†的时间戳。因此,除非您在所有这些不同来源的完全相同的时刻生成大量ID,否则ID实际上不可能会发生碰撞。
基于时间戳的不的GUID部分可以被认为是随机的;大多数GUID算法都将这些数字基于PRNG。因此,这些其他10个字节之间发生冲突的可能性与使用两个独立的随机数发生器并观察冲突的顺序相同。
考虑一下这一点 - PRNG可以并且确实重复数字,因此它们中的两个之间发生碰撞的可能性并不比仅使用其中一个的碰撞高得多,即使它们使用稍微不同的算法。这有点像每周播放相同的彩票号码而不是每周随机抽奖 - 获胜的几率完全相同。
现在,请记住,当您使用像Guid.Comb这样的算法时,您只有10位唯一符,相当于1024个单独的值。因此,如果您在相同的几毫秒内生成大量GUID,则将发生冲突。但是如果你以相当低的频率生成GUID,那么你同时使用多少种不同的算法并不重要,碰撞的可能性实际上是不存在的。
绝对确定的最好方法是进行测试;让所有2或3(或者你使用多少)同时以固定间隔生成GUID,并将它们写入日志文件,看看是否发生了冲突(如果是,有多少)。这应该让你对这在实践中的安全性有一个很好的了解。
P.S。如果您使用NHibernate的梳状生成器为集群主键生成GUID,请考虑使用NEWSEQUENTIALID()
而不是NEWID()
- 整个Comb点是为了避免页面拆分,而您没有实现如果您有其他进程使用非顺序算法。您还应该使用Guid.NewGuid
更改任何代码以使用相同的Comb生成器 - NHibernate中使用的实际Comb算法为not complicated,并且很容易在您自己的域逻辑中复制。
†请注意,似乎有一些关于NEWID
的争议,以及它是否包含时间戳。在任何情况下,由于它基于MAC地址,因此可能值的范围远小于V4 GUID或Comb。我建议坚持使用数据库外的Comb GUID和数据库中的NEWSEQUENTIALID
。
答案 1 :(得分:4)
是的,风险高于正常水平,因为所有这些都使用不同的“GUID”定义。 Guid.NewGuid()是符合RFC的大多数随机GUID,但NEWSEQUENTIALID是基于MAC地址和时间戳的重新排序(因此不符合RFC)GUID,NHibernate的梳理GUID完全不同(基于随机性和时间戳) )。
您可能只想考虑标准化一个GUID实现。我为我的所有应用程序使用自己的精梳GUID类型。 My blog简要描述了所有这些类型的GUID以及我自己的设计决策。