Algorithm 生成不完全全局唯一的标识符
我发现了许多关于生成UID的不同问题,但据我所知,我在这里的要求有些独特(ha) 总而言之:我需要生成一个非常短的ID,它是“本地”唯一的,但不必是“全局”或“通用”唯一的。这些限制不仅仅是基于美观或空间方面的考虑,而是由于这基本上被用作硬件标签,并且受到硬件的限制。以下是规格: 硬要求Algorithm 生成不完全全局唯一的标识符,algorithm,language-agnostic,unique,uniqueidentifier,Algorithm,Language Agnostic,Unique,Uniqueidentifier,我发现了许多关于生成UID的不同问题,但据我所知,我在这里的要求有些独特(ha) 总而言之:我需要生成一个非常短的ID,它是“本地”唯一的,但不必是“全局”或“通用”唯一的。这些限制不仅仅是基于美观或空间方面的考虑,而是由于这基本上被用作硬件标签,并且受到硬件的限制。以下是规格: 硬要求 ID必须仅包含十进制数字(基础数据为BCD) ID的最大长度为12个字符(数字) 必须脱机生成-数据库/web连接并非始终可用 软需求 我们希望从日历年和/或月份开始。由于这确实浪费了大量的熵,我不介意在
- ID必须仅包含十进制数字(基础数据为BCD)李>
- ID的最大长度为12个字符(数字)
- 必须脱机生成-数据库/web连接并非始终可用李>
- 我们希望从日历年和/或月份开始。由于这确实浪费了大量的熵,我不介意在这一点上妥协或完全放弃它(如果必要的话)
- 从特定机器生成的ID应按顺序显示
- ID不必按机器排序-例如,机器1可以吐出[123000124000125000],机器2可以吐出[123500123600124100]
- 然而,从集体意义上看,顺序性越强越好。像[200912000001、200912000002、200912000003,…]这样的一组ID将是完美的,尽管这显然不能跨多台机器进行扩展
- 此方案范围内的ID将最多由10台,也许100台不同的机器生成
- 总共生成的ID不会超过几百万个
- 并发性非常低。一台机器生成ID的频率不会超过每5分钟左右。而且,在同一小时甚至同一天内,一次生成ID的机器最多不超过5台。我预计在给定的机器上一天内生成的ID少于100个,而在所有机器上生成的ID少于500个
- 少数机器(3-5台)很可能负责生成超过80%的ID
现在我有机会睡一觉了,我想我实际上要做的是在默认情况下使用时间戳编码,并允许单个安装通过定义自己的2位或3位机器ID切换到机器顺序ID。这样,如果客户想弄乱ID,并将可读信息打包,他们可以自行选择确保唯一性的方法,我们对误用不负任何责任。也许我们可以提供一个服务器实用程序来处理所有联机安装时的机器id。在安装软件时,还应安装一个包含唯一数字id的机器id文件/注册表项。由于您只有几台机器,这不应超过3或4位数字。使用这些作为MS数字。从1开始依次生成剩余的数字。如何
yymmddhmmid
yy = two-digit year
MM = two-digit month
dd = two-digit day
hh = two-digit hour (24-hour time)
mm = two-digit minute
ID = machine-specific ID
示例:0912113201
来自ID=01的机器
或者(如果你不喜欢两位数的年份(Y2K lol)),那么yyyyymidxxxx
呢
yyyy = four-digit year
MM = two-digit month
ID = machine-specific ID
xxxx = sequentially-incremented integer
示例:200912010001
来自ID=01的机器
正如您所说,每台机器每五分钟最多只生成一个标识符,这为您每月提供8928(24*31*60/5=8928)个标识符的空间,这些标识符将适合xxxx
。如果您需要在xxxx
序列或机器ID中增加一个数字,您可以将年份压缩为三位数的年份yyy
(例如009)
这两个都符合您要求的时间戳/机器ID
我们都喜欢具体的代码:
class Machine {
public int ID { get; private set; }
public Machine(int id) {
ID = id;
}
}
class IdentifierGenerator {
readonly Machine machine;
int seed;
const int digits = 4;
readonly int modulus;
readonly string seedFormat;
public IdentifierGenerator(Machine machine) {
this.machine = machine;
this.modulus = (int)Math.Pow(10, digits);
this.seedFormat = new string('0', digits);
}
public string Generate() {
string identifier = DateTime.Now.ToString("yyyyMM")
+ machine.ID.ToString("00")
+ seed.ToString(seedFormat);
seed = (seed + 1) % modulus;
return identifier;
}
}
Machine m = new Machine(1);
IdentifierGenerator gen = new IdentifierGenerator(m);
Console.WriteLine(gen.Generate());
Console.WriteLine(gen.Generate());
产出:
200912010000
200912010001
24小时内有864000个100毫秒的刻度,因此将其固定在日期上可能会在09.12.24.86400.0起作用,但您必须丢失世纪才能容纳12位数字,并且您没有任何空间放置机器ID。想法一: YYMMDDMMNNN 在哪里 ~~ 想法二: 嗯 在哪里
mmmm is four digit code unique to the machine
nnnnnnnn is a sequential number.
我的建议是在一个id中结合多种方法。例如:从两个年份的数字开始,两个月的数字,然后生成一个随机数,将时间作为下几个数字的种子,然后为最后两个数字生成一个唯一的机器id。或者类似的东西。每台机器都有一个DDNNN的起始id,其中DD是唯一的机器标识符,NNN是该机器当天生成的当前标识符。每台机器跟踪它在特定日期生成的ID,并在需要新ID时通过将最后一个ID增加1来分配下一个ID。它在每天开始时将计数器重置为0。YYYYDOY日期在每台机器生成的数字之前(4位年份,3位年份)。由于机器标识符是唯一的,因此该编号保证是唯一的 如果您需要更多的空间来容纳更多的机器,您可以从年份中删除millenium,并为机器id添加一个数字:yyydoddnn “我在这里问这个问题的原因是 那么,是什么呢
mmmm is four digit code unique to the machine
nnnnnnnn is a sequential number.