不喜欢广告? 无广告 今天

UUID 与 ULID 与 CUID 你应该使用哪种唯一 ID?

发布日期
UUID 与 ULID 与 C-UID:你应该使用哪种唯一 ID?1
广告 移除?

每个数据库行、每个API资源、每个分布式事件都需要一个ID。问题不在于生成ID,而在于选择一种格式,以避免六个月后Postgres索引碎片化、URL看起来像噪音的情况。

此处是完整的 UUID生成器对比:UUID v4、UUID v7、ULID、CUID2和Snowflake——它们是什么、在哪些情况下会失效,以及你应该使用哪一个。

UUID v4:安全的默认选项(但有一个大问题)

UUID v4包含128位随机性,格式为 550e8400-e29b-41d4-a716-446655440000。它被全球广泛理解,被所有编程语言、所有数据库和所有ORM框架所支持。

碰撞概率几乎为零——你需要每秒生成十亿个UUID,持续85年,才可能遇到50%级别的单次碰撞概率。在实际应用中这并非问题。

问题是排序。UUID v4是 完全随机的,这意味着在UUID索引的表中插入行会将写入操作分散到B树的各个位置。在大规模场景下,这会导致页面分裂、索引碎片化和写入性能下降。如果你每秒插入数千行到MySQL或Postgres表的UUID主键中,你就会感受到这一点。

UUID v4作为字符串长度为36个字符——在不编码的情况下不适用于URL,且相比其他方案显得臃肿。

UUID v7:UUID v4的更好兄弟

UUID v7解决了排序问题。它是一种时间有序的UUID,其中最高有效位编码毫秒时间戳,其余部分是随机的。结果是: 01875f3a-7b2d-7f8e-a3d1-4b2e6c1a0f93.

按时间顺序插入的行在索引中大致保持连续。这对于写入密集型工作负载来说是重大优势。UUID v7与现有的所有UUID基础设施兼容——相同的格式、相同的字段长度、相同的库支持要求——同时增加了可排序性。

RFC在2022年最终确定,库支持正在快速跟进。如果你已经使用UUID且无法更改架构,从v4切换到v7风险低且收益高。

ULID:最符合开发者需求的选项

ULID(通用唯一字典排序标识符)将48位时间戳和80位随机性编码为26个Base32字符: 01ARZ3NDEKTSV4RRFFQ69G5FAV.

其突出特点:

  • 默认可排序 ——字典排序即时间顺序排序
  • URL安全 ——没有连字符,没有特殊字符
  • 不区分大小写 ——通过排除这些字符来避免 0/O1/I 歧义
  • 紧凑 ——26个字符,相比UUID字符串的36个字符更短

对于没有遗留约束的新项目,ULID是最实用的选择。它在大多数场景下足够可排序,URL中足够短,且人类可以轻松复制粘贴而不会出错。

一个注意事项:如果在同一个毫秒内生成多个ULID,其单调排序顺序在单个进程内是保证的,但在分布式节点之间则不保证。对于大多数应用程序来说,这已经足够了。

CUID2:专为分布式系统设计

CUID2是CUID的后继者,从零开始重新设计,以增强分布式环境下的安全性和抗碰撞能力。一个CUID2看起来像: clh3uj5ln0000qzrmn831mbhe.

它使用一个组合时间戳、计数器、指纹(进程ID + 主机名)和随机字节的SHA-3哈希。指纹是关键区别——它专门设计用于防止在多个服务器上同时运行多个ID生成器时发生碰撞。

CUID2是 不可排序的。它优先考虑抗碰撞和不可预测性,而非时间顺序。如果你正在构建一个由不可信客户端或大量独立节点生成ID的系统,并且安全是关键,那么CUID2值得这种权衡。

对于大多数后端API来说,这都过于复杂。

Snowflake ID:高吞吐量,但你需要自行管理

Snowflake ID最初由Twitter发明,用于在分布式集群中每秒生成数百万个唯一ID。一个Snowflake ID是64位整数:时间戳(41位)+ 数据中心ID(5位)+ 机器ID(5位)+ 序列号(12位)。

它们是可排序的,紧凑(适合放入 BIGINT),并且速度极快。Discord、Instagram和许多高规模系统都使用这种模式。

问题在于:你需要管理机器ID。这意味着需要一个协调服务(如ZooKeeper、etcd或数据库表)来为每个ID生成器分配唯一的机器ID。如果两个节点共享同一个机器ID,就会发生碰撞。正确设置这一点并不简单,且持续维护会带来操作开销。

除非你每秒生成数十万个ID,否则这种复杂性并不值得。

对比分析

UUID v4 UUID v4(随机 UUID)是一种通过随机数生成的全球唯一标识符,通常用于数据库记录、文件系统和网络应用程序中。它由32位二进制数组合而成,并以“-”分隔为五个部分:8-4-4-12。 **注意:** 此版本的UUID通常使用RFC 4122标准生成。 UUID v7 有效识别号 CUID2 Snowflake
可排序 是的 是的 是的
URL安全 否(无连字符) 否(无连字符) 是的 是的 是(整数)
抗碰撞 非常高 非常高 高的 非常高 高(需协调)
复杂 没有任何 没有任何 没有任何 低的 高的
典型应用场景 遗留系统、通用用途 数据库主键 API、URL、新项目 分布式/不可信客户端 高吞吐量系统

在Node.js中生成每个ID

// UUID v4
import { v4 as uuidv4 } from 'uuid';
console.log(uuidv4()); // '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'

// UUID v7
import { v7 as uuidv7 } from 'uuid';
console.log(uuidv7()); // '01875f3a-7b2d-7000-8000-4b2e6c1a0f93'

// ULID
import { ulid } from 'ulid';
console.log(ulid()); // '01ARZ3NDEKTSV4RRFFQ69G5FAV'

// CUID2
import { createId } from '@paralleldrive/cuid2';
console.log(createId()); // 'clh3uj5ln0000qzrmn831mbhe'

// Snowflake (using @socialgouv/nextid for simplicity)
import Snowflake from '@socialgouv/nextid';
const snowflake = new Snowflake(1n); // machine ID = 1
console.log(snowflake.nextId().toString()); // '1641024000000000001'

你可以直接使用 IO Tools UUID生成器 ——它支持UUID v1到v7,并支持批量生成,无需安装任何软件。

你应该选择哪一个?

以下是实际建议,而非“视情况而定”的敷衍说法:

  • 新项目,无遗留约束: 使用 有效识别号。可排序、URL安全、紧凑。它是最佳默认选择。
  • 已使用UUID,需要更好的数据库性能: 迁移到 UUID v7。直接升级,大幅改善索引性能。
  • 由客户端或在不可信的分布式节点上生成ID: 使用 CUID2。指纹机制使其在对抗性条件下仍能保持抗碰撞的鲁棒性。
  • 高吞吐量平台(每秒10万以上ID),并愿意管理机器ID: 使用 Snowflake。否则,无需考虑。
  • UUID v4: 仅在维护遗留代码且无法更改格式时使用。不要再为新表使用它。

默认使用UUID v4的时代已经结束。对于大多数场景,ULID是新的默认选择,如果你已经使用UUID,那么升级到UUID v7是正确的路径。选择一个并坚持下去。

想要享受无广告的体验吗? 立即无广告

安装我们的扩展

将 IO 工具添加到您最喜欢的浏览器,以便即时访问和更快地搜索

添加 Chrome 扩展程序 添加 边缘延伸 添加 Firefox 扩展 添加 Opera 扩展

记分板已到达!

记分板 是一种有趣的跟踪您游戏的方式,所有数据都存储在您的浏览器中。更多功能即将推出!

广告 移除?
广告 移除?
广告 移除?

新闻角 包含技术亮点

参与其中

帮助我们继续提供有价值的免费工具

给我买杯咖啡
广告 移除?