ULID 生成器
批量生成可作为 UUID 替代方案、按时间顺序可排序的 ID「ULID」。
使用小贴士
- 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(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 标识符」这一共同课题的不同解法而并存。