ULID 生成器

批量生成可作为 UUID 替代方案、按时间顺序可排序的 ID「ULID」。

什么是 ULID 生成

ULID 生成是指批量发行可按时刻排序的全局唯一标识符「ULID(Universally Unique Lexicographically Sortable Identifier)」。ULID 为26个字符的 Crockford Base32 字符串,前10个字符是表示生成时刻的时间戳部分,其余16个字符是由密码学安全随机数构成的随机部分。与 UUID v4 那样的完全随机标识符不同,其最大特点在于可按生成顺序以字符串方式排序。

本工具使用 Web Crypto API 的 crypto.getRandomValues() 生成随机部分,因此使用的是密码学上安全的随机源而非伪随机数。生成处理全部在浏览器内完成,输入的件数与生成结果不会发送至服务器。一次最多可批量生成1,000件,并同时支持大写(规范上的规范表记)与小写两种输出。

ULID 生成的使用方法

  1. 输入生成件数 在“生成件数”中输入希望一次发行的 ULID 个数,可在1~1000件的范围内指定。
  2. 选择是否需要小写显示 若在嵌入 URL 或日志时希望统一为小写,请勾选“以小写输出”。规范上大写与小写均为有效表记。
  3. 按下“生成”按钮 按下按钮后,会以当前时刻作为时间戳部分,按指定件数批量列出 ULID。
  4. 复制结果 可逐条使用“复制”,或使用以换行分隔一并复制全部列表的“全部复制”。

用好本工具的小技巧

  • ULID 的前 10 个字符是时间戳(生成时刻),其余 16 个字符为随机值。除非在同一毫秒内生成,仅按字符串排序即可还原生成时刻的先后顺序。
  • 如果数据库主键使用完全随机的 UUID v4,新行的插入位置会是随机的,容易导致 B-tree 索引碎片化;而 ULID 大致按时间顺序排列,插入位置相对连续,因此能缓解这一问题。
  • ULID 使用 26 个字符的 Crockford Base32 编码(从 `0`-`9`、`A`-`Z` 中去除容易混淆的 I、L、O、U,共 32 个字符),比 UUID(含连字符共 36 个字符)更短,在不区分大小写的环境中也能安全使用。
  • 如需与 Nano ID、UUID v4 进行格式对比,请参阅姊妹工具「Nano ID 生成」页面上的对比表。

ULID 生成派上用场的场景

数据库主键、记录 ID 的发行

在新表主键采用 ULID 时,可在开发初期批量准备用于测试虚拟记录或种子数据的 ID。

事件驱动系统的事件 ID

在消息队列或分布式系统中为每个事件赋予唯一 ID 时,按时刻排列的 ULID 更便于按时间顺序追踪日志。

日志、追踪 ID 的样例制作

可作为应用日志平台或追踪工具的动作确认、演示用数据,立即准备符合实际格式的 ID。

与其他格式 ID 的比较研究

若在 UUID v4、UUID v7 或用于短链接的 Nano ID 之间举棋不定,可先对比实际外观与字符数再决定采用。比较时也请一并使用UUID 生成・UUID v7 生成・Nano ID 生成各工具。

ULID 生成的相关术语

ULID
Universally Unique Lexicographically Sortable Identifier 的缩写。是128位的唯一标识符,同时前48位带有生成时刻,因此只需以字符串排序即可按时间顺序排列的规范。
Crockford Base32
由数字 0~9 与字母 A~Z 中去除外观易混淆的 I・L・O・U 四个字符后所构成的32个字符的编码方式。ULID 即以该方式编码为26个字符。
单调性(monotonicity)
指值随时间始终持续增大的性质。ULID 在同一毫秒内生成多个时不保证顺序,但使用规范所定的单调生成扩展实现,即可在同一毫秒内也维持单调递增。
UUID
Universally Unique Identifier 的缩写。是 RFC 4122 所规定的128位唯一标识符规范,使用36个字符(含连字符)的十六进制表记。与 ULID 是彼此独立的不同规范。
分布式系统中的唯一 ID
指多台服务器或进程无需向中央采号器询问,各自独立生成互不重复标识符的机制。ULID 与 UUID 为此用途结合生成时刻与随机数,把冲突概率降到极小。
时间戳部分
ULID 前10个字符所对应的部分,是把生成时刻以毫秒为单位编码为 Crockford Base32 的48位值。是仅凭字符串比较即可得知生成顺序这一机制的核心。

常见问题

ULID(Universally Unique Lexicographically Sortable Identifier,通用唯一按字典序排序标识符)是一种与 UUID 类似、可生成全局唯一 ID 的规范,其特点在于内含生成时刻的信息,因此仅按字符串排序即可得到按时间顺序排列的结果。

最大的区别在于「是否可按生成时间排序」。UUID v4 是完全随机的 128 位值,无法按生成顺序排序;而 ULID 的前 48 位是以毫秒为单位的时间戳,仅通过字符串比较就能得知生成顺序。此外表示形式也不同:ULID 为 26 个字符的 Base32,UUID 则为 36 个字符(含连字符)的十六进制数。

如果主键使用像 UUID v4 这样完全随机的值,新行在索引中的插入位置会是随机的,容易导致 B-tree 索引碎片化并降低缓存效率。由于 ULID 具有按时间顺序排列的特性,新行往往会被追加到索引末尾附近,因此据说能缓解这一问题。

前 10 个字符是 48 位的毫秒级时间戳(可表示至公元约 10889 年),其余 16 个字符是 80 位的随机值。总计 128 位,与 UUID 的位数相同,但同时内含时间信息,这正是 ULID 的特点。
工具君

闲话 ― 把「时间顺序」带入 ID 世界的 ULID

ULID 规范由 Alizain Feerasta 于 2016 年发布。当时 UUID 早已是分布式系统中生成唯一 ID 的标准手段,但其「完全随机因而无法排序」的特性,在数据库索引效率和日志的时间序列分析上颇为不便,ULID 正是为解决这一问题而诞生的。

事实上 UUID 也存在包含时间信息的变体,例如版本 1(MAC 地址+时间戳)以及 2024 年标准化的版本 7(时间戳+随机值的组合)。但 ULID 是独立于 UUID 规范(RFC 4122)之外的独立标准,其特点在于追求更简单的设计以及基于 Base32 的紧凑表示形式。

如今,几乎所有主流编程语言都有 ULID 的实现库,它被广泛应用于分布式系统的事件 ID、日志的追踪 ID、数据库主键等需要保留生成顺序的场景。它与同时期出现的 UUID v7 在设计理念上有诸多重合之处,二者作为「可排序的类 UUID 标识符」这一共同课题的不同解法而并存。