UUID 各版本详解:v4 真的够随机吗
最后更新:2026-09-14
UUID 是 128 位的标识符,标准写法是 32 个十六进制字符分成五组。它的设计目标是「无需中央协调即可生成全局唯一标识」,这正是分布式系统需要它的原因。
但「UUID」不是一种东西,而是多个版本共用同一种表示格式。各版本的生成依据不同,带来的性质也完全不同——选错版本会引入隐私问题或性能问题。
一、各版本的生成依据
- v1:基于时间戳与时序 + 生成节点的标识。可排序,但会暴露生成时间与节点信息,存在隐私顾虑;
- v2:基于用户与本地域信息,实际极少使用;
- v3 / v5:对命名空间与名称做散列(分别为 MD5 与 SHA-1),确定性——相同输入永远得到相同 UUID,适合做「同一资源在多个系统中的稳定标识」;
- v4:全部位随机(除版本与变体位)。最常用的版本,无顺序性;
- v6 / v7:时间有序的新版本。v7 以毫秒级时间戳打头,既近似可排序又是随机的,适合作为数据库主键;
- v8:保留给自定义实现,允许在标准格式内承载自定义的位布局。
二、v4 的碰撞概率到底有多大
v4 有 122 位随机信息,可表示约 5.3×10 的 36 次方种取值。直观的量级是:即使每秒生成十亿个 UUID 持续一百年,发生一次碰撞的概率仍远低于硬件出错的概率。
结论是:在业务系统中不需要为 v4 的碰撞做额外处理。真正需要担心的不是碰撞,而是「用错的随机源」——如果随机数来自可预测的种子,攻击者就能枚举出你生成的标识。
三、作为数据库主键的取舍
v4 不有序,作为主键会导致索引插入位置随机分散,在数据量大时造成明显的写放大与页分裂,性能下降。三种应对方式:
- 使用时间有序的版本(v6 / v7):近似递增,写入局部性好,同时保留随机性;
- 用组合键:自增列做聚集索引、UUID 做对外标识,兼顾写入性能与对外不可枚举;
- 坚持 v4 但调整存储:确认数据库对随机主键的写入退化程度可接受后再决定,而不是先上线再优化。
四、隐私与可枚举性
- v1 会把生成时间与节点标识编码进 UUID,拿到一串就能推断出生成时刻与机器信息,对外的资源标识不应使用 v1;
- 自增 ID 会泄露业务规模——从订单号就能看出平台今天卖了多少单,对外暴露时通常需要额外映射或改用 UUID;
- v3 / v5 是确定性的:只要知道命名空间与名称,任何人都能算出同样的 UUID,因此不能把它当作「随机标识」,它更适合做去重键或内容寻址。
五、作为口令或令牌使用的问题
UUID 常被顺手用作口令重置令牌或会话标识。需要注意:v4 的随机性对这类用途通常是够的,但格式固定、长度偏短,且若实现用了弱随机源就会退化。对安全敏感的令牌,更稳妥的做法是使用专门的随机令牌生成方式并设置较短的有效期与一次性使用。
顺带一提:绝不要用「哈希后的 UUID」代替认真的口令散列方案,理由见《MD5、SHA-1、SHA-256 怎么选》。
六、工具与延伸
批量生成 UUID 与随机密码可用 UUID 与密码生成工具。若正在比较主键方案的取舍,参见《UUID、自增 ID 还是雪花 ID》。