我发现了许多关于生成 UID 的不同问题,但据我所知,我的要求有些独特 (ha)。
总结一下:我需要生成一个非常短的 ID,它是“本地”唯一的,但不必是“全局”或“普遍”唯一的。这些限制不仅仅是基于审美或空间问题,而是因为它本质上被用作硬件标签并且受限于硬件的限制。以下是规范:
硬性要求
- ID只能包含十进制数字(底层数据为BCD);
- ID 的最大长度为 12 个字符(数字)。
- 必须离线生成——数据库/网络连接并不总是可用!
软需求
- 我们希望它以日历年和/或月份开始。由于这确实浪费了很多熵,我不介意对此做出妥协或完全废弃(如有必要)。
- 从特定机器生成的 ID 应该按顺序显示。
- ID 不必必须按机器排序 - 例如,机器 1 吐出 [123000, 124000, 125000],机器 2 吐出 [123500, 123600, 124100].
- 但是,从集体意义上看,顺序越多越好。一组 ID,如 [200912000001、200912000002、200912000003、...] 将是完美的,尽管这显然不能跨多台机器扩展。
使用场景:
- 此方案范围内的 ID 将从 10 台,最多可能是 100 台不同的机器生成。
- 生成的 ID 总数不会超过几百万。
- 并发性极低。一台机器不会比每 5 分钟左右更频繁地生成 ID。此外,很可能一次不超过 5 台机器会在同一小时甚至同一天生成 ID。我预计一天内在给定机器上生成的 ID 少于 100 个,所有机器生成的 ID 少于 500 个。
- 少数机器 (3-5) 很可能负责生成超过 80% 的 ID。
我知道可以使用少于 12 位十进制数字将时间戳编码到 100 毫秒甚至 10 毫秒精度,这足以保证此应用程序的“足够唯一”ID。我之所以在这里问这个问题,是因为我真的很想尝试在其中加入人类可读的年/月,或者对有关源机器的一些信息进行编码,或者两者兼而有之。
我希望有人可以帮助在这些软要求上做出妥协......或者解释为什么在给定其他要求的情况下它们都不可能。
(附:我的“母语”语言是 C#,但如果有人有任何绝妙的想法,任何语言甚至伪代码都可以。)
更新:
现在我已经有机会睡了,我想我实际上要做的是默认使用时间戳编码,并允许各个安装通过定义自己的来切换到机器顺序 ID 2 位或 3 位机器 ID。这样,想要弄乱 ID 并在人类可读信息中打包的客户可以找出他们自己的方法来确保唯一性,我们不对滥用负责。也许我们可以通过提供一个服务器实用程序来处理机器 ID(如果它们恰好在进行所有在线安装)来提供帮助。
最佳答案
"The reason I am asking this here on SO, is because I would really like to either try to incorporate human-readable year/month in there or encode some piece of information about the source machine, or both."
首先让我说我之前处理过这个问题,并且尝试将有用的信息存储到序列号中是一个长期的坏主意。设备序列号应该没有意义。就像数据库记录的主键应该是没有意义的。
当您开始尝试将真实数据放入您的序列号时,您只是将业务逻辑放入其中,您将被迫像维护任何其他代码一样维护它。 future 你会恨过去的你。相信我。 ;o)
如果您尝试存储日期/时间值,那么您将浪费带有无效时间/日期的数字空间。例如,您在月份字段中永远不会有大于 12 的值。
直接的纪元/单位时间计数器会更好,但对于每分钟只生成几个 id 的机器,你仍然会浪费大量空间。
12 位数字空间不大。查看维基百科上的 VIN 页面。只有几个制造商的空间,只有几千辆汽车。他们现在正在重复使用 VIN,因为他们通过将意义打包到其中而用完了空间。
http://en.wikipedia.org/wiki/VIN
这并不是说序列号中的所有含义都是不好的,只是严格限制以确保数字不会冲突。
像这样的……
- 位置 1-3:999 台机器
- 位置 4-12:序号
这就是您需要避免碰撞的全部。如果您添加一个位置数字,那么当您到达 11 个位置时,您就完蛋了。
抱歉,如果这听起来像是在咆哮。我处理了很多制造电子产品和各种机械零件的事情。除非有大量可用空间或辅助标签(-wow- 提供前面提到的必要 id 空间),否则它永远不会长期结束
关于algorithm - 生成一个不太全局唯一的标识符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1953797/