【发布时间】:2023-04-15 15:49:02
【问题描述】:
我需要从多个线程生成一个唯一的序列号。我在下面创建了一个简单的类,它似乎可以工作,但我不确定我是否可以依赖序列号是唯一的。
此外,如果数字超过 999999,我需要能够让数字回到 0。我预计它不会在很长一段时间内翻转,因为该方法每次调用的次数可能少于 100 次天。我知道系统会在有机会达到 999999 之前定期关闭进行维护。
GetSequenceNumber 方法将从 BizTalk 映射中的 xslt 转换调用,并且该方法可以同时调用多次(在同一个 BizTalk 主机实例中)。
在我的开发系统上,即使 BizTalk 同时多次调用该方法,它似乎也可以正常工作并生成不同的值。开发系统仅运行一个 BizTalk 主机实例。
但是,在生产系统上,有两台服务器。我是否认为这种方法不能保证跨服务器的唯一性,因为它们在不同的应用程序域中运行?
我不能使用 guid,因为序列号限制为 16 个字符。
public class HelperMethods
{
private static int sequenceNumber = 0;
public string GetSequenceNumber()
{
string result = null;
int seqNo = Interlocked.Increment(ref sequenceNumber);
result = string.Format("{0:MMddHHmmss}{1:000000}", DateTime.Now, seqNo);
return result;
}
}
我认为我可以使用服务器计算机名称并添加一些任意字符,这样即使一台服务器上生成的序列号与另一台服务器上生成的序列号相同,它仍然会有所不同,但我不是确定它会有多独特。像这样的:
string seqNumber = (MachineName == "Blah" ? "A" : "B") + GetSequenceNumber();
有人对我如何创建唯一的序列号有任何建议吗?它不必是完全独特的,我只需要非常不可能发生碰撞。另外,如果以线程安全的方式达到 1000000,如何将数字重置回 0?
【问题讨论】:
-
是否需要在
1000000处重置,还是您选择的任意高数字。例如,在int.MaxValue处滚动是否也可以接受?负数呢? -
如果您确定永远无法到达
int.MaxValue,请像现在一样增加计数器,但返回seqNo % 1000000。 -
这对你有用吗?
Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Substring(0, 16) -
@Enigmativity 据我所知,简单地截断 GUID 会有效地破坏您通过使用 GUID 获得的任何非冲突“保证”。见here
-
通常当您希望每条消息都有一个唯一编号时,您希望发送系统设置它。否则,在重试时,可能会为同一消息提供两个或多个数字。