有没有办法在每次100%新GUID时生成而没有任何机会在整个应用程序中发生冲突?
由于我无法在八小时内回答我的问题,我想出了解决方案:
internal static class GuidGenerator
{
private static readonly HashSet<Guid> _guids = new HashSet<Guid>();
internal static Guid GetOne()
{
Guid result;
lock (_guids)
while (!_guids.Add(result = Guid.NewGuid())) ;
return result;
}
internal static void Utilize(Guid guid)
{
lock (_guids)
_guids.Remove(guid);
}
}
此代码是否解决了应用程序中的问题?
编辑:呃,它变得复杂了。线程安全会降低速度。答案 0 :(得分:22)
不,没有办法生成绝对唯一的 GUID。只有 3.40282367×10 38 可能的GUID,因此星系会发生碰撞,因此这些标识符也会发生冲突。即使对于单个应用程序,它也取决于应用程序具有多少GUID。除非您的应用程序大于Google的所有索引器,否则您不需要为此而失眠。只需使用Guid.NewGuid()
。
答案 1 :(得分:16)
不确定。 GUID只是一个128位的值。因此,使用128位整数(例如由两个ulong
值表示)并递增它。当您达到128位整数类型的最大值时,您已生成所有可能的GUID。例如:
public IEnumerable<Guid> GetAllGuids()
{
unchecked
{
byte[] buffer = new byte[16];
ulong x = 0UL;
do
{
byte[] high = BitConverter.GetBytes(x);
Array.Copy(high, 0, buffer, 0, 8);
ulong y = 0UL;
do
{
y++;
byte[] low = BitConverter.GetBytes(y);
Array.Copy(low, 0, buffer, 8, 8);
yield return new Guid(buffer);
} while (y != 0UL);
x++;
} while (x != 0UL);
}
}
注意:
ulong
值很痛苦 - 我不喜欢 使用do...while
...... 当然,这绝不是随意的......
在实践中,正如其他人所提到的,Guid.NewGuid
发生碰撞的可能性非常小。
答案 2 :(得分:6)
不是100%。但是如果您的GUID生成器运行良好,则碰撞概率非常小。这实际上可以算作0。
随机生成的(第4类)guid有大约120个随机位。从生日问题中你可以看到,一旦你产生大约2 ^ 60或10 ^ 18个GUID,碰撞很可能会发生,这是一个很大的事情。
所以简单地使用Guid.NewGuid()
就足够了。
您提出的解决方案不是一个好主意IMO:
您的代码本身对我来说是正确的。即如果您注册所有GUID并且您的硬件完美运行,并且该软件没有其他错误,则保证不会发生冲突。
当然它也不是线程安全的,这对静态方法来说是意料之外的。
答案 3 :(得分:4)
如果您使用有限数量的字符,那么根据Pigeonhole(也称为Dirichlet
)原则,您将有可能收到碰撞。
答案 4 :(得分:3)
var newGuid = Guid.NewGuid();
http://msdn.microsoft.com/en-us/library/system.guid.newguid.aspx
编辑 - 我同意@David Heffernan所说的话。您可以使用适当的机制来生成最佳的唯一标识符,但是这个Universe中很少有东西可以依靠100%。
答案 5 :(得分:3)
如果您的上下文中需要唯一的GUID,请从00000000-0000-0000-0000-000000000000开始并使用增量。除非你达到FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF
,否则所有生成的GUID都是唯一的答案 6 :(得分:2)
这取决于你想要什么。如果您希望生成的GUID之间具有唯一性,则可以实现。只需维护一个GUID列表,无论何时需要创建一个新的GUID,都要循环,直到找到一个不在列表中的循环。
如果你想要某种全球唯一性,那么全球意味着在整个地球上使用的所有GUID中,那就永远无法实现。
答案 7 :(得分:2)
您可以使用Guid.NewGuid()
。它将为您生成GUID,我不相信您会与另一个GUID发生冲突。
答案 8 :(得分:2)
存储当前的GUID对于除了少量GUID之外的任何东西都是不切实际的 - 无论如何都会有极低的碰撞机会。
在现实世界中,您定期生成数百万甚至数十亿的GUID,存储128位值以确保唯一GUID的开销变得不切实际。 (每个GUID 16个字节)
仅需10,000,000,000个GUID,您需要160,000,000,000字节= 156,250,000 Kbytes = 152,588 Mbytes = 149 Gbytes
在大型表中查找时间也会使生成新的唯一GUID的速度变慢到虚拟爬网(在CPU时间范围内),特别是当新GUID与现有值冲突导致生成新GUID时 - 然后需要对其进行检查,等
生成&#39;随机&#39; 128位值,甚至使用像(当前时间*处理器时钟)这样的东西可能会足够接近&#39; - 只有45位足以存储1000年的毫秒数。 128位给你9,671,406,556,917,033,397,649,408倍的许多值。
无论你做什么,即使使用计数器,也会发生128位值的冲突。
答案 9 :(得分:1)
Guid.NewGuid()是生成不会与其他GUID冲突的GUID的最不可能的方式。除非您生成GUID并查看现有GUID以确保它们不存在,否则无法100%确定。
答案 10 :(得分:0)
GUID http://msdn.microsoft.com/en-us/library/system.guid.newguid.aspx
编辑-我同意@David Heffernan的说法。您可以在适当的位置使用该机制来生成最佳的唯一标识符,但是在此Universe中几乎没有什么东西可以指望100%的。