深入理解UUID

2021/07/06

UUID是什么

UUIDUniversally unique identifier 是一种唯一的字符串,用来标识一个设备或一个应用程序的唯一性。根据标准方法生成时,UUID 出于实用目的是唯一的。与大多数其他编号方案不同,它们的唯一性不依赖于中央注册机构或生成它们的各方之间的协调。虽然UUID 被复制的概率不是零,但它足够接近零,可以忽略不计.

UUID是固定长度128位,表示为 32 个十六进制(base-16)数字,显示在由连字符分隔的五组中,格式为 8-4-4-4-12 总共 36 个字符(32 个十六进制字符和 4 个连字符)例如:

123e4567-e89b-12d3-a456-426614174000 xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx

数字的四位M是 UUID 版本(version),数字的 1 到 3 位最高有效位是NUUID的变体(variant),在示例中,M是1,N是a(10xx 2 ),这意味着这是一个version-1、variant-1 的 UUID。

变体(variant)

UUID的变体(variant)字段,占1或2或3比特。RFC 4122定义了4种变体:

UUID的编码有很多种下面我只介绍Version 4 (random),

版本(version)

对于“变体(variants)1、2,标准中定义了五个版本(versions),在特定用例中每个版本可能比其他版本更合适。版本由 M 字符串中指示。

UUID的实现

浏览器提供了(crypto.randomUUID())[https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID] 用来生成UUID(version:4,variants:1),对于node也提供了对应接口,

它的实现相当简单

version位生成: & 0x0f | 0x40, 0x0f的二进制表示00001111, 0x40的二进制表示01000000, xxxxxxxx & 00001111即转换为0000xxxx, 0000xxxx | 01000000即转换为0100xxxx, variants位生成: & 0x3f | 0x80, 0x3f的二进制表示00111111, 0x80的二进制表示10000000, xxxxxxxx & 00111111即转换为00xxxxxx, 00xxxxxx | 10000000即转换为10xxxxxx

代码部分

const {
  getRandomValues
} = require('node:crypto').webcrypto;

// 缓存数据
const _data = new Uint8Array(16);
const _hex = [...Array.from({ length: 256 })].map((val, index) => index.toString(16).padStart(2, '0'));

function uuidv4() {
  // 给定的 typedArray 填充随机值
  getRandomValues(data);
  // set version bits
  data[6] = (data[6] & 0x0F) | 0x40;
  data[8] = (data[8] & 0x3F) | 0x80;
  return `${hex[data[0]]}${hex[data[1]]}${hex[data[2]]}${hex[data[3]]}`
    + `-${hex[data[4]]}${hex[data[5]]}`
    + `-${hex[data[6]]}${hex[data[7]]}`
    + `-${hex[data[8]]}${hex[data[9]]}`
    + `-${hex[data[10]]}${hex[data[11]]}${hex[data[12]]}${hex[data[13]]}${hex[data[14]]}${hex[data[15]]}`;
}