UUID.randomUUID()生成RFC 4122 v4随机UUID,基于SecureRandom,不暴露硬件或时间信息,碰撞概率极低,是Java中最通用、最稳妥的唯一ID生成方式。

直接调用标准库提供的随机或命名生成方法,就能得到符合 RFC 4122 规范的 UUID。关键不是“怎么拼”,而是“选对版本、用对方式、存对格式”。
优先用 v4 随机 UUID(最通用)
这是绝大多数场景的默认选择,不依赖硬件、不暴露时间或节点信息,碰撞概率低到可忽略。
- Java:用 UUID.randomUUID(),它严格实现 v4,底层基于 SecureRandom
- Python:用 uuid.uuid4(),同样为标准 v4 实现
- Go:用 github.com/gofrs/uuid/v5.NewV4(),轻量且线程安全
- 别手动拼字符串、别用 System.currentTimeMillis() + 随机数模拟——那不是 UUID,只是自造 ID
需要确定性结果时选 v3 或 v5(命名 UUID)
当相同输入必须产生相同 ID(比如把用户名转成固定 ID 做缓存键),就该用哈希型 UUID。
- v3 基于 MD5,输入字节数组后输出固定 UUID;v5 基于 SHA-1,更推荐(如 Python 的 uuid.uuid5(namespace_dns, "api.example.com"))
- 务必用 UTF-8 编码统一输入,例如 name.getBytes(StandardCharsets.UTF_8),避免编码差异导致结果不一致
- 命名空间要用标准预定义值,如 uuid.NAMESPACE_DNS 或 uuid.NAMESPACE_URL,不要自己瞎造
注意格式与存储,别让唯一性打折扣
生成只是第一步,存错类型会让性能和空间都出问题。
- 字符串形式是 8-4-4-4-12 共 36 字符(含连字符),如 f47ac10b-58cc-4372-a567-0e02b2c3d479
- 去连字符只需 .toString().replace("-", "")(Java)或 .hex(Python),得 32 位十六进制串
- 数据库里:MySQL 推荐存为 BINARY(16),PostgreSQL 直接用原生 UUID 类型;千万别塞进 VARCHAR(36) 当主键,索引会严重碎片化
避开常见陷阱
有些做法看似省事,实则埋雷。
- 不用 new UUID(most, least) 手动构造——除非你清楚每段 bit 的含义且有可靠来源
- 不拿 UUID 当时间序 ID 用——v1/v6/v7 虽含时间戳,但 v4 完全随机,无法排序
- 测试时别全局固定种子——单元测试可用固定值,但集成测试必须走真实随机逻辑,否则测不出分布式冲突
- 高并发写入场景(如订单表),慎用 UUID 做主键;考虑 Snowflake 等带时间前缀的方案替代

















