我试图在 DateTime 刻度和递增数字的帮助下在 C# 中生成唯一值。 伪代码:
- 从 DateTime.Now 滴答中取出最后 43 位有效位(我们将其命名为 A)
- 从递增序列中取出最后 21 位(我们将其命名为“B”)
- 左移“A”21 次(我们将其命名为“C”)
- 在 A 和 C 中进行二元或运算
我运行了生成 200 万个数字并插入到具有唯一约束集的数据库列的测试,它运行成功。
这是执行此操作的代码片段:
private static long _sequence = 1;
public static long GetUniqueNumber()
{
const int timeShift = 21;
var dateTime = DateTime.Now.Ticks;
const long dateTimeMask = ~(0L) >> timeShift;
const long sequenceMask = ((~(0L) >> (64 - timeShift)));
var seq = Interlocked.Increment(ref _sequence);
var dateTimeNo = (dateTimeMask & dateTime) << timeShift;
var seqNum = (seq & sequenceMask);
var num = dateTimeNo | seqNum;
return num;
}
我有两个问题: 1. 这个逻辑是否足以生成唯一数字? 2. 我发现一些生成的数字是'-ve',我不明白。
欢迎任何帮助/建议/改进。
最佳答案
Is this logic good enough to generate unique numbers
在什么范围内是独一无二的?跨多台计算机/进程/AppDomain
?当然不是。在单个 AppDomain
中?并不真地。生成 200 万个数字无关紧要 - 只是测试您的序列部分是否有效。 (221 刚刚超过 200 万。)
如果您可以在 DateTime.Now
的粒度内调用 GetUniqueNumber
221+1 次(这可能是 ~10- 15ms)然后你会得到一个重复。您是否测量过您的计算机调用它的速度有多快?
那么这 43 位将在 2<sup>43 滴答的时间内重复......或者至少如果你有一个足够细粒度的时钟。 (粒度迟早会对您不利。)
I find that some generated numbers are '-ve' which I didn't understand.
每当 dateTimeNo
设置了它的最高位(共 43 个)时,您将得到一个设置了最高位的 long
- 这意味着它将是否定的。
编辑:另请注意,您的换档已损坏。这:
const long dateTimeMask = ~(0L) >> timeShift;
执行了一个符号扩展移位 - 所以你只是以 ~0L 结束。
简而言之:使用Guid.NewGuid
.这就是它的用途。
关于用于生成唯一数字的 C# 按位操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9902153/