UUID 的全称是 Universally Unique Identifier,中文为通用唯一识别码。
构成:由一组32位数的16进制数字所构成。
格式:以连字号分为五段,表现形式为8-4-4-4-12的32个字符
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx 如:30385d15-0a88-42eb-bc43-2c000e9f778c
可以发现, 比较高的版本并不是一定更好,而是各自适合不同的应用场景。
使用有限的位数来表示可能无限的数据,那肯定是会复制的。那么重复的概率如何?
https://zelark.github.io/nano-id-cc/
这个工具可以可视化看到不同位数的重复概率,例如 21 位,以每小时产生 1000 个id 的情况下,17年后有 1% 的概率重复。
由于可能会重复,尽管概率很少,但总有一种不可预期的感觉。
根据 https://www.igiftidea.com/article/12183874318.html 这一文章这的这段话:
在一个前雇主,我们有一个包含随机 uuid 的独特列。我们在部署后的第一周发生了碰撞。当然,几率很低,但不是零。这就是 Log4j 2 包含 UuidUtil.getTimeBasedUuid 的原因。只要您在单个服务器上每秒生成的 UUID 不超过 10,000 个,它就会生成一个在 8,925 年内唯一的 UUID。
那么我们在 javascript 中是否存在在这样的方法呢?
经过搜索, getTimeBasedUuid 应该就是 基于时间戳的 uuid v1.
生成可排序的 uuid:
v1 虽然是基于时间戳的, 但时间戳并没有在 uuid 字符串的前面, 如果要让其可以排序, 需要做一些处理:
const uuidV1 = require('uuid/v1'); function v1UuidCompare(a, b) { a = a.replace(/^(.{8})-(.{4})-(.{4})/, '$3-$2-$1'); b = b.replace(/^(.{8})-(.{4})-(.{4})/, '$3-$2-$1'); return a < b ? -1 : (a > b ? 1 : 0); } > v1UuidCompare(uuidV1(), uuidV1()) -1
如果程序有不同的要求,则可以选择不同的 uuid 版本。
v1 - 必须需要保证唯一性,且是在单个线程中运行。
v4 - 容错性比较好,比如友好的错误处理。
v3,v5 - 使用相同参数可重复的 uuid。
function broofa() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8); return v.toString(16); }); } console.log(broofa())
/* Assuming that self.crypto.randomUUID() is available */ let uuid = self.crypto.randomUUID(); console.log(uuid); // for example "36b8f84d-df4e-4d49-b662-bcde71a8764f"
https://npmjs.com/package/nanoid
import { nanoid } from 'nanoid' model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"
https://www.npmjs.com/package/uuid
const { v4: uuidv4 } = require('uuid'); uuidv4(); // ⇨ '1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed'