UUID理解
UUID v4 为什么不会重复?
UUID v4 用 randomUUID()(Node 内置 crypto 模块)生成,格式为 8-4-4-4-12 分组的 36 位字符串,例如 3f2504e0-4f89-41d3-9a0c-0305e82c3301。
核心原因
UUID v4 不是绝对保证唯一,而是靠海量随机空间把碰撞概率压到几乎为零。
它就像一次抽 122 位的"超级随机数",可能的结果多到什么程度呢?
- 取值空间大到离谱:一共 2¹²² 种可能,比地球上所有沙子的数量还多得多。随手抽一个,和别人撞上的概率,比连续中好几次头奖还低。
- 不是"伪随机":底层用的是密码学级别的随机(和加密用的同一套),不像
Math.random()那样有规律可循,所以不会偷偷重复。 - 撞一次要等多久:哪怕每秒生成 10 亿个 UUID,也要连续不停生成大约 85 年,才可能出现一次重复。现实中根本到不了这个量级。
什么是"伪随机"(假随机)?
计算机算不出真正的随机,所谓随机数其实是用一个固定公式算出来的:给它一个起始值(叫种子 seed),它就从种子开始一步步往下算,结果看着很乱,但本质是确定、可复现的 —— 种子相同,算出来的一串数就完全一样。这就是"假"的由来:有规律、能被推算。
- 普通伪随机(
Math.random()):种子简单、容易猜,别人能推算出你后面会出什么。 - 密码学安全随机(
randomUUID()):种子来自操作系统采集的真实世界噪声(如硬件事件的纳秒级时刻、CPU 的硬件随机源等),谁也无法复现或猜到,所以生成的值无法被预测、无法被伪造。
这就是 sessionId 要用 randomUUID() 而不是 Math.random() 的原因:后者可能被人推算出来,导致 ID 被冒用。
和时间戳有关系吗?
v4 版本(即 randomUUID())和时间戳没有任何关系,122 位全部是纯随机数,不含时间信息:
- 同一毫秒生成 100 个,或隔一年再生成,规律完全一样,都是重新抽随机数。
- 好处:不泄露生成时间、不暴露先后顺序,隐私性好。
- 代价:生成出来的 ID 是乱序的,无法通过 ID 判断谁先谁后。
不过 UUID 还有别的版本是专门基于时间的:
| 版本 | 依据 | 特点 |
|---|---|---|
| v1 | 时间戳 + MAC 地址 | 含生成时间,但会泄露机器网卡地址 |
| v7 | 毫秒时间戳 + 随机数 | 新标准,按时间递增,兼顾有序和随机 |
| v4 | 纯随机 | 无时间信息(当前使用的版本) |
如果希望 ID 大致按创建时间有序,可以考虑 v7。它对数据库更友好,主要体现在两点:
- 索引写入更快:数据库主键索引(B+ 树)是按 ID 大小排好序存放的。v7 的 ID 递增,新数据永远追加到末尾,不用挪动老数据;v4 的 ID 随机,新数据会插到中间任意位置,容易触发"页分裂"(挪数据、开新页),写入更慢。打个比方:随机 ID 像往一叠排好序的卡片中间到处硬塞,递增 ID 像一张张往最后叠,后者显然轻松得多。
- 范围查询更方便:v7 的 ID 本身隐含时间顺序(ID 大 ≈ 创建晚),想查"最近的数据"或"某时间段的数据",直接按主键排序/范围取即可,时间相近的数据在索引里物理位置也挨在一起,扫描快;v4 完全随机,做不到这点,通常还得额外建一个时间字段的索引。
但 Node 内置的 randomUUID() 目前只支持 v4,想用 v7 需引第三方库(如 uuid 包的 v7())。
小结
无需任何人统一分配、本地随手就能生成、几乎不可能重复 —— 所以特别适合用来生成各种唯一标识。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)