使用方法
- 在「生成数量」填 10(示例值),只接受 1~100 的整数。数量只决定一次输出几条,不改变任何一条的随机位数——生成 100 条和生成 1 条,每一条都是同样强度的 v4。
- 「连字符」默认保留,得到规范的 8-4-4-4-12 写法,共 36 个字符,可直接粘进 PostgreSQL 的
uuid列。 - 要写进属性值或日志字段时把「包裹形式」切到花括号,得到 38 字符写法;要写进 URN 字段时切到
urn:uuid:前缀,得到 45 字符写法。三种一次只能选一种。 - 「输出大小写」只改变外观:
C21E25B5-…与c21e25b5-…是同一个 128 位值,字节内容完全一致,多数数据库在比较时也不区分。 - 点「生成 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 位随机。落到代码上是两行位运算:
b[6] = (b[6] & 0x0f) | 0x40:第 7 个字节(下标 6)的高 4 位清空后强制写成0100,也就是版本号 4;低 4 位保留原样。b[8] = (b[8] & 0x3f) | 0x80:第 9 个字节(下标 8)的高 2 位清空后强制写成10,也就是 RFC 4122 的变体;低 6 位保留原样。
为什么把固定位放在这两处。因为输出字符串按 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 逐项核对:
- 长度 36,4 个连字符把 32 个十六进制字符切成 8 / 4 / 4 / 4 / 12 五组;
- 去掉连字符是
c21e25b534864c4784632f18f63813bb,共 32 个字符,正好 32 × 4 = 128 位; - 第三组是
4c47,首位4——版本位固定生效; - 第四组是
8463,首位8,落在允许的8/9/a/b里——变体位固定生效; - 固定位合计 4 + 2 = 6 位,所以每条的随机位是 128 − 6 = 122 位;
- 「包裹形式」选花括号后同一条会写成
{c21e25b5-3486-4c47-8463-2f18f63813bb}(38 字符),选 URN 后写成urn:uuid:c21e25b5-3486-4c47-8463-2f18f63813bb(45 字符),三者的 128 位内容完全相同。
这 10 条两两不同的概率是 1 − C(10,2) / 2122,即 1 减去约 4.2×10-35,实际就是 100%。换句话说,在这个量级上"撞号"不是需要预防的风险,只是需要知道的理论边界。
输出形式与逐字节位图对照表
先看同一 128 位值的几种写法,字符数差异全部来自包裹符号而不是内容:
| 写法 | 示例 | 字符数 | 适用场景 |
|---|---|---|---|
| 标准小写 | c21e25b5-3486-4c47-8463-2f18f63813bb | 36 | 数据库 uuid 列、接口参数 |
| 标准大写 | C21E25B5-3486-4C47-8463-2F18F63813BB | 36 | 要求全大写的旧系统 |
| 无连字符 | c21e25b534864c4784632f18f63813bb | 32 | 紧凑存储、文件名 |
| 花括号 | {c21e25b5-3486-4c47-8463-2f18f63813bb} | 38 | 属性值、部分 SDK |
| URN | urn:uuid:c21e25b5-3486-4c47-8463-2f18f63813bb | 45 | XML、RDF、日志标识 |
下面这张表把首条示例的 16 个字节逐一摊开。「十六进制序号」指的是去掉连字符后的字符位置——第 1 个字节对应第 1~2 个字符,第 16 个字节对应第 31~32 个字符。「固定位」一栏是这一字节里被强制写死的位数,16 行加起来正好 6 位。
| 字节 | 十六进制序号 | 示例值 | 固定位 | 随机位 | 说明 |
|---|---|---|---|---|---|
| 1 | 1-2 | c2 | 0 | 8 | 第 1 组第 1 字节,无任何约束 |
| 2 | 3-4 | 1e | 0 | 8 | 第 1 组第 2 字节,无约束 |
| 3 | 5-6 | 25 | 0 | 8 | 第 1 组第 3 字节,无约束 |
| 4 | 7-8 | b5 | 0 | 8 | 第 1 组最后一字节,其后插入第 1 个连字符 |
| 5 | 9-10 | 34 | 0 | 8 | 第 2 组第 1 字节,无约束 |
| 6 | 11-12 | 86 | 0 | 8 | 第 2 组最后一字节,其后插入第 2 个连字符 |
| 7 | 13-14 | 4c | 4 | 4 | 版本字节:高 4 位固定 0100,十六进制首位恒为 4 |
| 8 | 15-16 | 47 | 0 | 8 | 第 3 组最后一字节,其后插入第 3 个连字符 |
| 9 | 17-18 | 84 | 2 | 6 | 变体字节:高 2 位固定 10,十六进制首位恒为 8/9/a/b |
| 10 | 19-20 | 63 | 0 | 8 | 第 4 组第 2 字节,其后插入第 4 个连字符 |
| 11 | 21-22 | 2f | 0 | 8 | 第 4 组第 3 字节,无约束 |
| 12 | 23-24 | 18 | 0 | 8 | 第 4 组第 4 字节,无约束 |
| 13 | 25-26 | f6 | 0 | 8 | 第 4 组第 5 字节,无约束 |
| 14 | 27-28 | 38 | 0 | 8 | 第 4 组第 6 字节,无约束 |
| 15 | 29-30 | 13 | 0 | 8 | 第 4 组第 7 字节,无约束 |
| 16 | 31-32 | bb | 0 | 8 | 第 4 组最后一字节,标识符到此结束 |
| 合计 | 1-32 | 16 字节 | 6 | 122 | 固定 6 位 + 随机 122 位 = 128 位 |
把两张表放在一起能看出一件事:所有写法共享同一份 128 位数据,变的是外壳。数据库里存哪个形式只影响字段长度与比较开销,不影响唯一性。
边界与精度说明
- 随机位是 122 位,不是 128 位。那 6 位被版本号和变体号占走了。想用满 128 位,得到的是"像 v4 但不合规"的串,解析器可能拒绝。
- 数量 1~100 的整数。只接受整数,
10.5、abc、空值、负数、0 都会被拒绝并给出具体提示。数量不影响单条强度。 - 三种包裹形式互斥。花括号和 URN 前缀同时选会得到两种标准都不认的写法,因此页面直接拒绝,而不是默默挑一个。
- 大小写与连字符不改变内容。三种写法是同一个值,唯一性完全一致,不必为了"更随机"而在大小写上纠结。
- 碰撞概率与生成量平方成正比。109 条时约 9.404×10-20,1012 条时约 9.404×10-14,1015 条时约 9.404×10-8,1018 条时约 9.404×10-2。放量到十亿级之前,这个数字都不需要你操心。
- 用
Math.random()拼装会把安全性打回原点。它的内部状态只有 128 位且不保证密码学安全,观察两三个连续输出即可反推后续值。本页所有随机字节都来自crypto.getRandomValues,不提供"用伪随机凑一个"的降级开关。 - 不适合当排序主键。v4 的字节随机,插入顺序与键序无关,B 树会不断页分裂与随机写放大。要么保留自增或时间有序主键、把 v4 放进唯一索引列,要么改用时间有序的版本——但本页不生成那些版本。
- 随机不等于加密,也不等于授权。不可预测只是说"猜不到下一条",它不提供机密性、不提供签名、也不证明持有者有权访问。把标识符当访问凭据时,权限校验仍然必须由服务端完成。
常见问题
为什么第三组的第一个字符总是 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 前缀四种外壳可切换。需要自定义字符池拼短串,或需要时间有序的编号,都不在本页范围。