我尝试在我们的C#应用程序中使用long作为唯一ID(不是全局的,仅用于一个会话)用于我们的事件.你知道以下是否会生成一个唯一的长ID?
public long GenerateId()
{
byte[] buffer = Guid.NewGuid().ToByteArray();
return BitConverter.ToInt64(buffer, 0);
}
Run Code Online (Sandbox Code Playgroud)
为什么我们不直接使用GUID?我们认为8字节长就足够了.
Mat*_*lia 12
不,它不会.正如在Raymond Chen的博客上多次强调的那样,GUID被设计为整体上是独一无二的,如果你只删除它的一部分(例如,只从其128中删除64个字节),它将失去其(伪)唯一性保证.
这是:
客户需要生成一个8字节的唯一值,他们最初的想法是生成一个GUID并丢弃后半部分,保留前八个字节.他们想知道这是不是一个好主意.
不,这不是一个好主意.(...)一旦你看到这一切是如何工作的,很明显你不能丢弃GUID的一部分,因为所有部分(除了固定部分)一起工作以建立唯一性.如果你取走这三个部分中的任何一个,算法就会崩溃.特别是,只保留前8个字节(64位)可以得到时间戳和4个常量位; 换句话说,你拥有的只是一个时间戳,而不是GUID.
由于它只是一个时间戳,因此可能会发生冲突.如果两台计算机同时生成这些"截断的GUID"之一,它们将生成相同的结果.或者,如果系统时钟由于时钟复位而及时反转,您将开始重新生成第一次生成的GUID.
我尝试在我们的C#应用程序中使用long作为唯一ID(不是全局的,仅用于一个会话.)用于我们的事件.你知道以下内容会产生一个独特的长ID吗?
你为什么不用柜台?
您无法将 16 位值提炼为 8 位值,同时仍保持相同程度的唯一性。如果唯一性很重要,不要“推出你自己的”任何东西。除非您真的知道自己在做什么,否则请坚持使用 GUID。
如果相对简单的唯一性实现就足够了,那么生成您自己的 ID 仍然比从 GUID 派生它们更好。以下代码片段摘自我经常使用的“本地唯一标识符”类。它可以轻松定义字符输出的长度和范围。
using System.Security.Cryptography;
using System.Text;
public class LUID
{
private static readonly RNGCryptoServiceProvider RandomGenerator = new RNGCryptoServiceProvider();
private static readonly char[] ValidCharacters = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789".ToCharArray();
public const int DefaultLength = 6;
private static int counter = 0;
public static string Generate(int length = DefaultLength)
{
var randomData = new byte[length];
RandomGenerator.GetNonZeroBytes(randomData);
var result = new StringBuilder(DefaultLength);
foreach (var value in randomData)
{
counter = (counter + value) % (ValidCharacters.Length - 1);
result.Append(ValidCharacters[counter]);
}
return result.ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,为了明确的人类可读输出,它排除了 1(一)、I(i)、0(零)和 O(o)。
为了确定有效字符和 ID 长度的特定组合的“唯一性”有多有效,数学很简单,但拥有各种“代码证明”(Xunit)仍然很好:
[Fact]
public void Does_not_generate_collisions_within_reasonable_number_of_iterations()
{
var ids = new HashSet<string>();
var minimumAcceptibleIterations = 10000;
for (int i = 0; i < minimumAcceptibleIterations; i++)
{
var result = LUID.Generate();
Assert.True(!ids.Contains(result), $"Collision on run {i} with ID '{result}'");
ids.Add(result);
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
11602 次 |
最近记录: |