如何生成唯一且不可预测的 ID

Posted 无恨星晨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何生成唯一且不可预测的 ID相关的知识,希望对你有一定的参考价值。

通常数据库可以生成唯一的 ID,最多的就是数字序列,也有像 MongoDB 这样产生组合序列的,不过这种形式的 ID 由于是序列,是可以预测的。如果想得到不可预测且唯一的 ID,方法还是有的。

下面主要以 Node.js 的环境为例。

Node-uuid

Github 上有个 node-uuid 项目,它可以快速地生成符合 RFC4122 规范 version 1 或者 version 4 的 UUID。

安装,既可以通过 npm install node-uuid ,也可以在 package.json 中定义。使用方式:

var uuid = require(node-uuid);
 
// 产生一个 v1 (基于时间的) id
uuid.v1(); // -> ‘6c84fb90-12c4-11e1-840d-7b25c5ee775a‘
uuid.v1().replace(/-/g, "")
 
// 产生一个 v4 (随机) id
uuid.v4(); // -> ‘110ec58a-a0f2-4ac4-8393-c866d813b8d1’
uuid.v4().replace(/-/g, "")

听起来很有保证,只是……有点太长了。

坊间也有一些在 UUID 基础上随机截取几位的办法来组成一个新的短一点的字符串,只不过唯一性就又重新成为一个问号了。

Hashids

另外一个方法,来自 hashids,它的原理就是从数字经过一个加盐(salted)算法产生一个哈希(hash)字符串。这样算法就是通过混淆使结果具有不可预测性,而唯一性依然由数字本身来达成,从而得到(类似 youtube 里的)足够短,不可预测且唯一的 ID。

安装方式类似,只是 hashids 建议使用一个固定的版本。比如在 package.json 中

"dependencies": {
  "hashids": "0.3.3"
}

使用方法也很简单。先设定一个字符串作为 salt。

var Hashids = require("hashids"),
    hashids = new Hashids("this is my salt”);

然后对数字(准确来说是数字数组)进行编码

var hash = hashids.encrypt(12345);
// Nkk9
 
var hash = hashids.encrypt(683, 94108, 123, 5);
// aBMswoO2UB3Sj

对数组编码可以有很有趣的用法,比如需要在一个分布式的环境里使用,可以使用机器编号 + 序列数字组合数组然后再编码。

有编码就有解码

var numbers = hashids.decrypt("NkK9”);
// [12345]

编码的输出会随着数字的增大而变长,为了达到足够混淆,它可以指定最少长度。

hashids = new Hashids("this is my salt", 8);
 
var hash = hashids.encrypt(1);
// gB0NV05e

还有其它选项,比如控制输出所使用的字符,编码 MongoDB 的 ObjectId 等等。

上面介绍的两个项目,各有各优缺点,不过目的是一致的,可以根据实际情况选用。两个项目在其它语言上也有类似的实现。

 

以上是关于如何生成唯一且不可预测的 ID的主要内容,如果未能解决你的问题,请参考以下文章

hashids 了解

Android能够获取到唯一的设备ID吗

场景应用:id全局唯一且自增,如何实现?

场景应用:id全局唯一且自增,如何实现?

如何在 Apple 设备上获取唯一且一致的设备 ID

分布式服务自增长唯一ID小结