alltools.one
Development
2025-07-03
7 min
alltools.one Team
UUIDIdentifierDatabaseAPIDevelopment

UUID 指南:版本、格式与最佳实践

UUID(通用唯一标识符)是 128 位标识符,设计为在空间和时间上唯一,无需中央权威机构。它们是分布式系统的标准选择,在这些系统中,独立生成 ID — 无需协调 — 至关重要。

UUID 格式

UUID 是一个 128 位数字,以 32 个十六进制数字显示,分为五组,用连字符分隔:

550e8400-e29b-41d4-a716-446655440000
^^^^^^^^ ^^^^ ^^^^ ^^^^ ^^^^^^^^^^^^
time-low  mid  hi   clk   node
               +ver  +var
  • 总计:128 位(16 字节)
  • 字符串长度:36 个字符(32 个十六进制 + 4 个连字符)
  • 版本:编码在第 13 个字符("hi" 半字节)中
  • 变体:编码在第 17 个字符中

使用我们的 UUID 生成器 即时生成 UUID。

UUID 版本

UUID v1:基于时间

由当前时间戳和机器的 MAC 地址生成。

// 结构:时间戳(60 位)+ 时钟序列(14 位)+ 节点(48 位)
6ba7b810-9dad-11d1-80b4-00c04fd430c8

优点:按创建时间自然排序,每台机器保证唯一。 缺点:暴露 MAC 地址(隐私问题),可能泄露创建时间。 使用场景:需要时间排序且在受控环境中时。

UUID v4:随机

由加密安全随机数生成。这是使用最广泛的版本。

// 122 个随机位(6 位保留给版本和变体)
f47ac10b-58cc-4372-a567-0e02b2c3d479

优点:简单,无信息泄露,无需协调。 缺点:不可排序,数据库索引性能略低于顺序 ID。 使用场景:通用目的 — 这是大多数应用的默认选择。

UUID v7:时间排序随机(新标准)

最新版本(RFC 9562,2024),结合 Unix 时间戳和随机数据。

// 结构:时间戳(48 位)+ 随机(74 位)
018e7b50-4a00-7000-8000-000000000001

优点:自然按时间排序,出色的数据库索引性能,除毫秒精度外无信息泄露。 缺点:较新,某些库可能尚不支持。 使用场景:需要按时间排序的唯一 ID — 非常适合数据库主键。

其他版本

  • UUID v3:命名空间和名称的 MD5 哈希。确定性的。
  • UUID v5:命名空间和名称的 SHA-1 哈希。确定性的,优于 v3。
  • UUID v6:重新排序的 v1,以获得更好的可排序性。已被 v7 取代。
  • Nil UUID:全零(00000000-0000-0000-0000-000000000000)。用作哨兵值。

碰撞概率

随机生成的 UUID(v4)碰撞的可能性有多大?有 122 个随机位:

  • 生成 10 亿个 UUID 后:概率 ≈ 10^18 分之一
  • 达到 50% 碰撞概率:需要大约 2.7 × 10^18 个 UUID
  • 以每秒 10 亿个 UUID 的速度:大约需要 86 年

出于所有实际目的,UUID v4 碰撞不会发生。你遇到硬件故障的可能性要大得多。

UUID 与其他 ID 格式对比

格式长度可排序唯一URL 安全
UUID v436 字符
UUID v736 字符
ULID26 字符
nanoid21 字符大概率
自增可变单表内
Snowflake ID18-19 字符单系统内

ULID(通用唯一字典序可排序标识符)

ULID 是一种紧凑的替代方案:48 位时间戳 + 80 位随机数,编码为 26 个 Crockford Base32 字符。它们按创建时间进行字典序排序。

何时使用自增 ID

顺序 ID 对于单数据库应用更简单、更高效。在以下情况使用 UUID:

  • 需要多个系统独立生成 ID
  • 不希望向外部用户暴露插入顺序
  • 分布式数据库需要可合并的 ID

数据库性能考虑

随机 UUID(v4)导致 B 树索引碎片化,因为插入发生在随机位置。在大表上,这可能使写入性能降低 2-5 倍。

解决方案

  1. 使用 UUID v7:时间排序的 UUID 按顺序插入,匹配自增性能
  2. 以二进制存储:使用 BINARY(16) 而不是 CHAR(36) 可节省 55% 的存储空间
  3. 使用 ULID:可排序且比 UUID 更紧凑
-- PostgreSQL:原生 UUID 类型(16 字节,高效)
CREATE TABLE users (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  name TEXT NOT NULL
);

-- MySQL:以 BINARY(16) 存储以提高性能
CREATE TABLE users (
  id BINARY(16) PRIMARY KEY,
  name VARCHAR(255) NOT NULL
);

生成 UUID

命令行

# macOS/Linux
uuidgen

# Python 单行命令
python3 -c "import uuid; print(uuid.uuid4())"

JavaScript

// 内置(Node.js 19+,现代浏览器)
crypto.randomUUID();

// UUID v7(使用 uuid 包)
import { v7 } from 'uuid';
const id = v7();

Python

import uuid
uuid.uuid4()  # 随机
uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com')  # 基于名称

如需无需编码快速生成,我们的 UUID 生成器 可在浏览器中即时创建 v4 UUID。

常见问题

我应该使用 UUID 还是自增整数作为数据库主键?

对于单数据库应用,自增整数更简单、更快速。对于分布式系统、微服务,或者需要在数据库插入之前在客户端生成 ID 的情况,UUID(最好是 v7)是更好的选择。如果你使用 PostgreSQL,原生 UUID 支持使性能差异可以忽略不计。

UUID 可以用作安全令牌吗?

UUID v4 使用来自加密源的 122 位随机数,提供良好的熵。然而,对于安全令牌(API 密钥、会话 ID),最好使用具有附加属性的专用令牌格式,如校验和、过期编码或前缀标识。UUID 用于身份标识,而非认证。

相关资源

Published on 2025-07-03
UUID Guide: Versions, Formats, and Best Practices | alltools.one