UUID生成器

按 RFC 4122 §4.4 生成标准 v4 标识符:128 位里 122 位随机,版本位与变体位按规范固定,再按 8-4-4-4-12 分组输出 36 位十六进制串。

示例展示(演示值,点「生成 UUID」重新生成,勿直接当作生产数据):
c21e25b5-3486-4c47-8463-2f18f63813bb
e029b633-a45e-4ad3-b482-5fee43a3d3e9
1bad8bb2-211f-44a5-a622-8422a8af2286
63450054-d1f4-44ff-be2f-a105e6426755
abe315ae-dc5f-4783-a93c-1d0fddf202ae
9d5da9d7-5601-49d5-93a6-834872292efc
5d68edd5-6684-4eab-870d-150b1a3e8a41
8c35004b-b771-4e5a-88f0-65a512bbfd3e
35456f6a-a69b-4749-b3d3-ea22d61a22ef
c32bce20-b968-4b2c-a129-44ddaf3448c7

提示:数量输入框里裸按 Enter 可直接重新生成;刷新页面或再点一次按钮都会得到完全不同的一批;本页不写入浏览器存储,也不发送任何网络请求。

使用方法

  1. 在「生成数量」填 10(示例值),只接受 1~100 的整数。数量只决定一次输出几条,不改变任何一条的随机位数——生成 100 条和生成 1 条,每一条都是同样强度的 v4。
  2. 「连字符」默认保留,得到规范的 8-4-4-4-12 写法,共 36 个字符,可直接粘进 PostgreSQL 的 uuid 列。
  3. 要写进属性值或日志字段时把「包裹形式」切到花括号,得到 38 字符写法;要写进 URN 字段时切到 urn:uuid: 前缀,得到 45 字符写法。三种一次只能选一种。
  4. 「输出大小写」只改变外观:C21E25B5-… 与 c21e25b5-… 是同一个 128 位值,字节内容完全一致,多数数据库在比较时也不区分。
  5. 点「生成 UUID」立刻输出;数量输入框里裸按 Enter 同样触发。「复制全部」一行一条带走,「导出 CSV」存成带 BOM 的表格,Excel 打开不乱码。

这个 UUID生成器能解决什么问题

一是把对外 ID 和内部主键分开。很多系统的自增主键会在 URL 里暴露业务量——对手看到 /order/10231 就知道你出了多少单。用 122 位随机的标识符做对外编号、内部继续用自增列做聚簇主键,既藏住规模,也没牺牲索引性能。

二是多库、多端并发写入时不需要号段服务。分库分表或离线端先写数据后同步时,号段服务本身就是一个单点和故障源。这个 UUID生成器生成的结果不依赖任何中心节点,两台互不通信的机器各自生成,撞车概率低到可以忽略。

三是给临时资源命名。对象存储的上传文件名、导出任务的 job id、重试用的幂等键,这些标识只要唯一就够,不需要可读,也不需要连续。先把这类名字统一成 v4,能避免"用时间戳命名然后同一毫秒撞名"的经典事故。

四是批量造测试数据。一次输出 100 条互不相同的标识符,直接粘进 fixture 或 SQL 的 INSERT,不用手编再核对重号。

本页不做:不生成 v1、v3、v5、v7 这些时间序或命名派生版本;不做加密、签名、哈希;不校验标识符是否被重复使用。想自定义字符池造短随机串请用「随机字符串生成器」;想把二进制字节转成文本请用「Base64 编码」。

生成原理:122 位随机与 RFC 4122 §4.4 的位布局

这个 UUID生成器只做三件事:取随机字节、按规范改写两个字节、按分组拼成字符串。

第一步取随机数。核心就一行:crypto.getRandomValues(new Uint8Array(16))。它是 W3C Web Cryptography API 定义的接口,随机源来自操作系统的熵池,由浏览器实现保证密码学强度,页面里不引入任何第三方随机库。处于安全上下文(https 或 localhost)时也可以直接用 crypto.randomUUID(),它内部做的就是同一件事。

第二步摆位。RFC 4122 §4.4 把 16 个字节的 128 位分成三部分:4 位版本、2 位变体、其余 122 位随机。落到代码上是两行位运算:

为什么把固定位放在这两处。因为输出字符串按 8-4-4-4-12 分组,第 7 字节正好是第三组的第一个字节,第 9 字节正好是第四组的第一个字节。于是第三组的首个十六进制字符恒为 4,第四组的首个十六进制字符恒为 8、9、a、b 之一——解析器不用读完全串就能认出"这是 v4、这是 RFC 4122 变体"。把固定位塞在分组头部是为了让格式自校验,代价是只剩 122 位随机。

第三步拼装。16 个字节按小写十六进制展开成 32 个字符,再在第 8、12、16、20 个字符之后各插一个连字符,共 36 个字符。128 ÷ 4 = 32,每个十六进制字符正好承载 4 位;再加 4 个连字符就是 36。

为什么不干脆用 Math.random()。两笔账都不划算。第一,IEEE 754 binary64 的尾数只有 52 位,单次调用最多区分 252 = 4503599627370496 个取值,凑够 122 位至少要取 3 次。第二,也是更要命的一条:ECMAScript 只要求它返回 [0,1) 且分布大致均匀,不要求密码学安全;以 V8 为例底层是 xorshift128+,内部状态仅 128 位,观察到两三个连续输出就能反推状态、预测后面的每一个值。v4 常被当成"猜不到就不能访问"的凭据,这类串在对手眼里是有规律的。

熵与碰撞。独立均匀的前提下,一条 v4 的熵正好是 122 位,取值空间 2122 ≈ 5.317×1036。碰撞概率按生日问题近似为 n² / (2 × 2122),具体量级写在下面的边界说明里。要让碰撞概率升到 50%,需要大约 1.1774 × 261 ≈ 2.715×1018 条——以每秒 109 条的速度不停生成也要 86.0 年,每秒 106 条则要 86031 年。

依据的标准。位布局出自 RFC 4122 §4.4《Algorithms for Creating a UUID from Truly Random or Pseudo-Random Numbers》;该文档在 2024 年 5 月被 RFC 9562 取代,但 v4 的位布局一字未改,两者可互相印证,再往上是 ISO/IEC 9834-8 与 ITU-T X.667 定义的 UUID 本体。你可以按上面的位位置自行复核每一条输出。

完整示例(数值仅作演示)

示例条件就是页面打开时的默认值:数量 10 条、小写、保留连字符、不包裹。下面这组是默认条件下真机生成的结果,仅作排版演示。

c21e25b5-3486-4c47-8463-2f18f63813bb
e029b633-a45e-4ad3-b482-5fee43a3d3e9
1bad8bb2-211f-44a5-a622-8422a8af2286
63450054-d1f4-44ff-be2f-a105e6426755
abe315ae-dc5f-4783-a93c-1d0fddf202ae
9d5da9d7-5601-49d5-93a6-834872292efc
5d68edd5-6684-4eab-870d-150b1a3e8a41
8c35004b-b771-4e5a-88f0-65a512bbfd3e
35456f6a-a69b-4749-b3d3-ea22d61a22ef
c32bce20-b968-4b2c-a129-44ddaf3448c7

拿首条 c21e25b5-3486-4c47-8463-2f18f63813bb 逐项核对:

这 10 条两两不同的概率是 1 − C(10,2) / 2122,即 1 减去约 4.2×10-35,实际就是 100%。换句话说,在这个量级上"撞号"不是需要预防的风险,只是需要知道的理论边界。

输出形式与逐字节位图对照表

先看同一 128 位值的几种写法,字符数差异全部来自包裹符号而不是内容:

写法示例字符数适用场景
标准小写c21e25b5-3486-4c47-8463-2f18f63813bb36数据库 uuid 列、接口参数
标准大写C21E25B5-3486-4C47-8463-2F18F63813BB36要求全大写的旧系统
无连字符c21e25b534864c4784632f18f63813bb32紧凑存储、文件名
花括号{c21e25b5-3486-4c47-8463-2f18f63813bb}38属性值、部分 SDK
URNurn:uuid:c21e25b5-3486-4c47-8463-2f18f63813bb45XML、RDF、日志标识

下面这张表把首条示例的 16 个字节逐一摊开。「十六进制序号」指的是去掉连字符后的字符位置——第 1 个字节对应第 1~2 个字符,第 16 个字节对应第 31~32 个字符。「固定位」一栏是这一字节里被强制写死的位数,16 行加起来正好 6 位。

字节十六进制序号示例值固定位随机位说明
11-2c208第 1 组第 1 字节,无任何约束
23-41e08第 1 组第 2 字节,无约束
35-62508第 1 组第 3 字节,无约束
47-8b508第 1 组最后一字节,其后插入第 1 个连字符
59-103408第 2 组第 1 字节,无约束
611-128608第 2 组最后一字节,其后插入第 2 个连字符
713-144c44版本字节:高 4 位固定 0100,十六进制首位恒为 4
815-164708第 3 组最后一字节,其后插入第 3 个连字符
917-188426变体字节:高 2 位固定 10,十六进制首位恒为 8/9/a/b
1019-206308第 4 组第 2 字节,其后插入第 4 个连字符
1121-222f08第 4 组第 3 字节,无约束
1223-241808第 4 组第 4 字节,无约束
1325-26f608第 4 组第 5 字节,无约束
1427-283808第 4 组第 6 字节,无约束
1529-301308第 4 组第 7 字节,无约束
1631-32bb08第 4 组最后一字节,标识符到此结束
合计1-3216 字节6122固定 6 位 + 随机 122 位 = 128 位

把两张表放在一起能看出一件事:所有写法共享同一份 128 位数据,变的是外壳。数据库里存哪个形式只影响字段长度与比较开销,不影响唯一性。

边界与精度说明

常见问题

为什么第三组的第一个字符总是 4?

因为那是版本号。RFC 4122 §4.4 规定第 7 个字节高 4 位固定写成 0100,也就是十进制 4,而第 7 个字节恰好是第三组的第一个字节,所以第三组永远以 4 开头。反过来说,第三组首位不是 4,它就不是合规的 v4。

第四组首位的 8、9、a、b 是什么意思?

那是变体位。第 9 个字节的高 2 位固定为 10,这个十六进制字符只能落在 1000~1011,即 8、9、a、b 之一,用来把本变体与更早的几种区分开。

大写形式、去连字符、加花括号会改变唯一性吗?

不会。这三种都只是外观层变化,底层 128 位一个字节都没动。真正影响唯一性的是随机位数——固定 122 位。选哪种只看接收方的解析器认哪一种。

一次能生成多少条?100 条会重复吗?

上限 100 条。以 109 条规模算,两条相同的概率约 9.404×10-20,100 条内部两两比对更是低到没有实际意义。更大的批量分几次生成即可,每次点按钮都是全新的独立抽取。

生成的 UUID 会上传或保存到服务器吗?

不会。随机字节由浏览器接口产生,位运算和拼接都在当前页面完成,没有网络请求,也不写 localStorage 或 Cookie。打开开发者工具的 Network 面板连点几次「生成 UUID」即可自行确认。

可以拿 UUID 当数据库主键吗?

能当主键,但别当聚簇主键。随机序插入会让 B 树不断分裂、随机写放大,索引体积和写入延迟明显变差。常见做法是内部主键仍用自增整数,把 v4 放到独立的唯一索引列上专做对外标识。

UUID 不可预测,是不是就能当密码或者密钥用?

这是两个概念。122 位随机确实"猜不到",但随机不等于加密:它不提供机密性、完整性,也不做认证。把 v4 当访问令牌用时,服务端仍必须校验权限与有效期;把它当密钥材料用时,请走专门的密钥派生流程。

本页和别的唯一标识符工具有什么区别?

本页只做 RFC 4122 §4.4 定义的 v4:固定 122 位随机、第三组首位恒为 4、第四组首位恒为 8/9/a/b,大小写、连字符、花括号、URN 前缀四种外壳可切换。需要自定义字符池拼短串,或需要时间有序的编号,都不在本页范围。

相关工具