我试图在DateTime滴答和增加数字的帮助下在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;
}
我有两个问题: 这个逻辑是否足以产生唯一数字? 2.我发现一些生成的数字是'-ve',我不明白。
欢迎任何帮助/建议/改进。
答案 0 :(得分:6)
这个逻辑是否足以产生唯一数字
在什么范围内有独特之处?跨多个计算机/进程/ AppDomain
s?当然不是。在一个AppDomain
内?并不是的。生成200万个数字是无关紧要的 - 那就是只是测试你的序列部分是否有效。 (2 21 刚刚超过200万。)
如果您可以在GetUniqueNumber
(可能是~10-15ms)的粒度内拨打DateTime.Now
2 21 +1次,那么您将得到一个重复。你有没有测量过你的计算机可以称之为多快?
然后有这样的事实:这些43位将在2 43 ticks'时间重复......或者至少如果你有一个足够细粒度的时钟。 (迟早,粒度会对你不利。)
我发现有些生成的数字是'-ve',我不明白。
每当dateTimeNo
设置了最高位(43位)时,您最终会设置一个long
并设置最高位 - 这意味着它将为负数。
编辑:还要注意你的换档是坏的。这样:
const long dateTimeMask = ~(0L) >> timeShift;
执行符号扩展转换 - 所以你最终只能得到~0L。
简而言之:使用Guid.NewGuid
。这就是它的用途。
答案 1 :(得分:0)
负数是由于长期实施。由于它是带符号的数字,如果在位操作之后位64的MSB变为'1',则该数字将变为负数。没什么可担心的。