前提最近发现各个频道推荐了很多ULID
相关文章,这里对ULID
的规范文件进行解读,并且基于Java
语言自行实现ULID
, 通过此实现过程展示ULID
的底层原理 。
ULID出现的背景
![ULID规范解读与实现原理](http://img.zhejianglong.com/231018/14435952Z-0.png)
文章插图
ULID
全称是Universally Unique Lexicographically Sortable Identifier
,直译过来就是通用唯一按字典排序的标识符,它的原始仓库是https://github.com/ulid/javascript
,该项目由前端开发者alizain发起,基于JavaScript
语言编写 。从项目中的commit
历史来看已经超过了5
年,理论上得到充分的实践验证 。ULID
出现的原因是一些开发者认为主流的UUID
方案在许多场景下可能不是最优的,存在下面的原因:UUID
不是128 bit
随机编码(由128 bit
随机数通过编码生成字符串)的最高效实现方式UUID
的v1/v2
实现在许多环境中是不切实际的,因为这两个版本的的实现需要访问唯一的、稳定的MAC
地址UUID
的v3/v5
实现需要唯一的种子,并且产生随机分布的ID
, 这可能会导致在许多数据结构中出现碎片UUID
的v4
除了随机性之外不需要提供其他信息 , 随机性可能会在许多数据结构中导致碎片
UUID
的v1/v2
实现依赖唯一稳定MAC
地址不现实,v3/v4/v5
实现因为随机性产生的ID
会"碎片化" 。基于此提出了
ULID
,它用起来像这样:ulid() // 01ARZ3NDEKTSV4RRFFQ69G5FAV
ULID
的特点如下:- 设计为
128 bit
大小,与UUID
兼容 - 每毫秒生成
1.21e+24
个唯一的ULID
(高性能) - 按字典顺序(字母顺序)排序
- 标准编码为
26
个字符的字符串,而不是像UUID
那样需要36
个字符 - 使用
Crockford
的base32
算法来提高效率和可读性(每个字符5 bit
) - 不区分大小写
- 没有特殊字符串(
URL
安全,不需要进行二次URL
编码) - 单调排序(正确地检测并处理相同的毫秒,所谓单调性,就是毫秒数相同的情况下,能够确保新的
ULID
随机部分的在最低有效位上加1
位)
ULID
规范在ULID/javascript
类库中实现,此二进制格式目前没有在JavaScript
中实现: 01AN4Z07BY79KA1307SR9X4MV3|----------||----------------| TimestampRandomness48bits80bits
组成时间戳(Timestamp
)- 占据
48 bit
(high
) - 本质是
UNIX-time
,单位为毫秒 - 直到公元
10889
年才会用完
Randomness
)- 占据
80 bit
(low
) - 如果可能的话,使用加密安全的随机源
ASCII
字符集 。在相同的毫秒(时间戳)内,无法保证排序顺序 。规范的表示形式
ULID
规范的字符串表示形式如下:ttttttttttrrrrrrrrrrrrrrrrwheret is Timestamp (10 characters)r is Randomness (16 characters)
也就是:- 时间戳占据高(左边)
10
个(编码后的)字符 - 随机数占据低(右边)
16
个(编码后的)字符
ULID
规范的字符串表示形式的长度是确定的,共占据26
个字符 。编码使用
Crockford Base32
编码算法,这个编码算法的字母表如下:0123456789ABCDEFGHJKMNPQRSTVWXYZ
该字母表排除了I
、 L
、O
、U
字母,目的是避免混淆和滥用 。此算法实现不难 , 它的官网有详细的算法说明(见https://www.crockford.com/base32.html
):![ULID规范解读与实现原理](http://img.zhejianglong.com/231018/14435a459-1.png)
文章插图
单调性(如果启用了单调性这个特性为前提下)当在相同的毫秒内生成多个
ULID
时,可以保证排序的顺序 。也就是说,如果检测到相同的毫秒,则随机分量在最低有效位上加1
位(带进位) 。例如:
推荐阅读
- vite vue3 规范化与Git Hooks
- 钩子 【pytest官方文档】解读-插件开发之hooks 函数
- 中 ?打造企业自己代码规范IDEA插件
- HashMap底层原理及jdk1.8源码解读
- JS 模块化-05 ES Module & 4 大规范总结
- 上 ?打造企业自己代码规范IDEA插件
- Go 源码解读|如何用好 errors 库的 errors.Is 与 errors.As() 方法
- 高二化学重要知识难点解读
- 2022年装修全流程保姆级解读 85平米的房子装修需要多少钱
- 国家安全用电规范 国家安全用电常识