ULID(Universally Unique Lexicographically Sortable Identifier) 是一种轻量级、全局唯一、可排序的标识符格式,是 UUID 的一个优秀替代方案。结合了 UUID 的唯一性和时间顺序性,在分布式系统中非常实用。
一、ULID 的特点
特性 | 描述 |
长度 | 26个字符(比 UUID 的 36 字符更短) |
编码方式 | 使用 Crockford Base32 编码(无大小写敏感,不含 ILOU 等易混淆字符) |
结构 | 前 10 位表示时间戳,后 16 位为随机数 |
排序性 | 可按字典序排序,且时间越晚生成的 ULID 越大 |
唯一性 | 在同一毫秒内通过随机熵保证唯一性 |
紧凑性 | 比 UUID 更短,适合日志、URL、数据库主键等场景 |
示例:
01ARZ3NDEKTSV4RRFFQ69G5FA2
二、ULID 结构详解
ULID 是由两个部分组成:
1. 时间戳部分(前 10 个字符)
- 表示自 Unix 时间起点(1970-01-01)以来的毫秒数。
- 占用 48 位,因此可以使用到公元 10,889 年
2. 随机部分(后 16 个字符)
- 使用 80 位随机数,确保在同一毫秒内生成多个 ULID 也不会重复。
- 如果使用加密安全的随机源,ULID 也可以是“加密安全”的。
三、ULID 相较于 UUID 的优势
对比项 | UUID v4 | ULID |
长度 | 36 字符 | 26 字符 |
是否有序 | 无序 | 按时间排序 |
是否可预测 | 不可预测 | 可预测(取决于实现) |
是否适合数据库主键 | 有性能问题 | 推荐 |
是否适合用于日志、API、URL | 较长 | 更友好 |
是否支持加密安全 | 支持 | 可支持 |
四、应用场景推荐
场景 | 推荐使用 ULID? |
分布式系统 | |
数据库主键(MySQL、PostgreSQL 等) | |
日志 ID、事件 ID | |
API 返回 ID(如 RESTful 接口) | |
URL Slug、短链接 | |
高并发写入场景 | (相比 UUID 更优) |
五、各语言实现(开源库)
以下是主流语言对 ULID 的支持:
语言 | 库名 | GitHub / 链接 |
Python | ulid-py | https://github.com/ahawker/ulid |
JavaScript | ulid | https://www.npmjs.com/package/ulid |
Go | go-ulid | https://github.com/oklog/ulid |
Java | ulid-java | https://github.com/ulid4j/ulid4j |
Rust | ulid-rs | https://github.com/ulid-rs/ulid |
PHP | symfony/uid | Symfony 内置支持 ULID |
Ruby | ulid gem | https://rubygems.org/gems/ulid |
六、Python 示例:使用 ulid-py
pip install ulid-py
import ulid
# 生成一个新的 ULID
uid = ulid.new()
print(uid) # 输出类似:01ARZ3NDEKTSV4RRFFQ69G5FA2
# 将 ULID 转换为字符串
print(str(uid))
# 获取 ULID 的时间戳部分
timestamp = uid.timestamp()
print(timestamp.datetime) # 输出对应的 datetime 对象
七、MySQL 中如何存储 ULID?
建议使用 CHAR(26) 或 VARCHAR(26) 类型来存储 ULID:
CREATE TABLE example (
id CHAR(26) PRIMARY KEY,
name VARCHAR(255)
);
如果追求更高的效率,也可以将时间戳部分和随机部分拆分成两个字段进行存储。
八、与 Snowflake ID 的比较
特性 | ULID | Snowflake |
唯一性 | ||
可排序 | ||
可读性 | 不直观 | |
实现复杂度 | 简单 | 复杂(需部署节点 ID、时钟同步) |
依赖中心服务 | 否 | 通常需要 |
存储空间 | 26 字符 | 64 位整数 |
安全性 | 可加密安全 | 可预测(如果知道算法) |
九、总结:什么时候应该使用 ULID?
推荐使用 ULID 的情况:
- 你希望 ID 有一定的排序性;
- 你希望在不同服务之间生成唯一的 ID;
- 你需要一个比 UUID 更短、更友好的 ID;
- 你不希望引入复杂的 ID 生成服务(如 Snowflake);
- 你想在日志、API、前端展示中使用简洁的 ID。
不建议使用 ULID 的情况:
- 你对 ID 的生成速度要求极高;
- 你需要严格的加密安全性(虽然 ULID 可以做到,但不是默认);
- 你的系统已经使用了 Snowflake 或其他成熟方案。
如果正在设计一个新系统,并希望选择一个既具备唯一性又具有一定排序性的 ID 方案,ULID 是一个非常值得考虑的选择。