文章插图
这 18 位数字中的前 6 位表示的是地区,也就是省份、城市和区县,随后的 8 位表示的是出生年月日,接下来的 3 位才同时表示 ID 和性别,最后 1 位用于做校验码防止出现身份证号输错的情况 。用上述图中的黄色部分中有一半的数字是用来表示出生的男性,另一半表示出生的女性,所以如果同一个地区的同一天,同时出生了 501 位男性或者女性就会导致潜在的重复问题 。
上面谈到的问题其实也是我们在各种业务场景中经常能够遇到的问题,18 位的数字中真正用于表示序列的 ID 其实只有 1000 的一半,如果 18 位数都是无意义的,那它们可以表示 10 亿亿个人,但是一旦在 ID 中引入了业务上的具体信息,就增加了冲突的可能性 。
业务记录上主键的长度往往都是固定的,大多数业务的主键都会使用整数,它的上限一般就是 2^64,如果这些位数都用来表示记录的 ID,那么在有生之年基本上是不可能被使用完的,但是一旦我们将业务信息加入 ID,就会让原本无意义的 ID 变得有意义从而影响它的唯一性 。
另一个比较类似的例子其实是分布式的 ID 生成器,Snowflake 算法会为 64 个比特的整数赋予不同的信息:
范围长度作用0-01不使用1-4141毫秒级时间戳42-465数据中心标识符47-515机器标识符52-6312序列号
从这个设计来看,我们的假设其实是一台机器上一毫秒最多只能生成 4096 个 ID,一旦超过了这个这个数量就有可能导致 ID 冲突或者乱序,从而失去其唯一性;这个算法中涉及的时间戳、数据中心标识符、机器标识符都没有办法解决唯一性的问题,哪怕这三者完全相等,最终还是有冲突的可能,我们仍然需要使用无其他意义的序列号来保证 ID 的唯一 。
总结其实不难看出,使用无意义 ID 的主要目的就是利用它的唯一性保证对象的标识符不会发生冲突,无意义 ID 的唯一作用就是保证唯一性,这能帮助我们避免业务字段可能存在潜在冲突的可能,这也提示我们想要使用联合字段构成主键时一定要深思熟虑 。
如果我们想要在具有唯一性的标识符中加入业务信息,一定要注意这可能会减少用于保证唯一性的『空间』,当然对于一个足够大的空间来说,这其实并没有什么问题;但是类型为 int64 的 ID 中加入业务数据还是需要仔细思考可扩展性以及预留的信息是否足够业务的发展 。
到最后,我们还是来看一些比较开放的相关问题,有兴趣的读者可以仔细思考一下下面的问题:
- 软件工程还有哪些场景利用了 ID 的唯一性?
- 在日常生活中除了身份证号之外,还有哪些 ID 也有比较高的冲突可能性?
【身份证上的 ID 能保证唯一性么?】
推荐阅读
- 情绪对人体免疫力的影响
- 世界上木质最硬的树 铁桦树有多硬
- 收藏|10个实用的珠宝行业术语,知道6个以上的都是行家。
- 全棉、纯棉、精梳棉、针织棉棉料的区别
- 为什么你长得好看却不上镜?
- 梦到树林里有各种不同的鸟 梦见一群鸟在树上
- 自动挡上坡,动力不足该如何换挡?换不好有可能车毁人亡?
- 世界上所有的犀牛种类 世界上有多少种犀牛
- 不花钱就能解决的25个汽车故障,建议收藏!
- 梦到坐船在水上行驶水里有许多鱼 梦到坐船在水上游玩