放弃使用UUID,ULID才是更好的选择!

💡 原文中文,约3200字,阅读约需8分钟。
📝

内容提要

ULID是一种通用唯一词典分类标识符,与UUID相比具有更好的性能和可读性。ULID基于时间戳和随机数,每毫秒内有1.21e + 24个随机数可选,不存在冲突的风险。ULID可以替代数据库自增id和UUID,在分布式环境下全局唯一且有序。使用ULID可以按照时间排序数据库,也可以嵌入时间戳进行分区分表。在Python中,可以使用ulid-py库来生成和操作ULID。

🔎

延伸解读

ULID与UUID的核心差异

ULID同时包含48位时间戳和80位随机数,而UUID要么基于随机数(如UUID4),要么基于时间戳(如UUID1)。这种结构使ULID在保持全局唯一性的同时,天然具备按时间排序的能力。UUID4虽然随机性强,但缺乏时间信息,且存在理论上的冲突风险。ULID的随机部分每毫秒有1.21e+24种可能,冲突概率极低。

ULID的编码与可读性优势

ULID使用Crockford的Base32编码,生成26个字符的字符串,而UUID是36个字符。Base32字母表排除了I、L、O、U,避免视觉混淆,且不区分大小写、无特殊字符,对URL和用户输入更友好。这种编码在存储和传输时更高效,也更容易被人工识别和记录。

ULID在数据库与分布式系统中的应用

ULID可以替代数据库自增ID,无需数据库参与主键生成,适合分布式环境。由于ULID有序,可以直接用于按时间排序,甚至替代单独的created_at字段。如果按日期分区分表,ULID中嵌入的时间戳能帮助定位正确的分区。但需注意,同一毫秒内的ULID顺序无法保证,若业务需要严格毫秒内有序,需额外处理。

Python中使用ULID的注意事项

通过ulid-py库可以方便地生成和操作ULID。ulid.new()基于当前时间和os.urandom()生成;也支持从UUID、时间戳或随机数创建。ULID对象提供timestamp()和randomness()方法获取各部分快照。使用时需注意,ULID的时间戳精度为毫秒,且随机部分依赖系统随机源,在安全性要求极高的场景应确认随机源是否加密安全。

❓

Q&A

ULID与UUID相比有哪些优势?

ULID在性能和可读性上优于UUID,避免了冲突风险,并且支持按字典顺序排序。

ULID的组成是什么?

ULID由48位的时间戳和80位的随机数组成,时间戳精确到毫秒。

如何在Python中生成ULID?

可以使用ulid-py库,通过调用ulid.new()来生成新的ULID。

ULID适合哪些应用场景?

ULID适合替代数据库自增id、在分布式环境中使用以及按日期分区等场景。

ULID的编码方式是什么?

ULID使用Crockford的base32编码,规范为26个字符,不包含特殊字符,且不区分大小写。

UUID的主要缺陷是什么?

UUID存在冲突风险,尤其是UUID4版本,且不同版本的UUID在生成和使用上各有缺陷。

➡️

继续阅读