Appearance
TMID
1. TMID 概述
TMID(Tenon-Mortise Id)是一个 16 字节(128 位)的分布式 Id,灵感源于 Snowflake Id 和 ULID。
TMID V1.0,依次由以下要素组成:
时间戳(48 bit),毫秒级时间戳:
通过计算:
可得,从
EPOCH开始共计可以使用 8925 年左右。Note:
EPOCH默认值为1733745600000L(即2024-12-09T20:00:00+08:00),支持自定义EPOCH。序列号(16 bit),与时间戳无关,每台机器每生成 65,536 个 Id 为一轮计数;
机器 Id(16 bit),支持同时由 65,536 台机器生成同一资源的 Id;
随机数(48 bit):
单机每毫秒百万亿级的随机性。
2. TMID vs Snowflake Id vs ULID vs GUID
| 特性 | TMID | Snowflake Id | ULID | GUID v4 |
|---|---|---|---|---|
| 大小 | 128 位(16 字节) | 64 位(8 字节) | 128 位(16 字节) | 128 位(16 字节) |
| 时间戳 | 48 位(毫秒精度) | 41 位(毫秒精度) | 48 位(毫秒精度) | 不包含 |
| 序列号 | 16 位 | 12 位 | 不包含 | 不包含 |
| 机器 Id | 16 位 | 10 位 | 不包含 | 不包含 |
| 随机数 | 48 位 | 不包含 | 80 位的随机数 | 128 位随机数 |
| 有序性 | 时间有序 | 时间有序 | 时间有序 | 无序 |
| 可预测性 | 随机数部分极低 | 较高 | 随机数部分极低 | 极低 |
| 可追溯性 | 可追溯 | 可追溯 | 不可追溯 | 不可追溯 |
| 范围扫描风险 | 无 | 较低 | 无 | 无 |
| 数据库索引支持 | 好 | 好 | 好 | 差 可导致页分裂 |
| 可用年限 | 8925 年左右 | 69 年左右 | 8925 左右 | 不限 |
| 时间回拨问题 | 可视为无 | 可能导致 Id 重复 | 可视为无 | 无 |
| 适用场景 | 高并发分布式系统数据库主键 | 高并发分布式系统数据库主键 | 高并发分布式系统数据库主键 | 令牌 |
| 表示法 | BASE64 | 整型 | BASE32 | BASE16,按 8-4-4-4-12 分隔表示 |
| 示例 | AAAF4ubFAAEBgPBBjKfDKw== | 1292658282840139 | 01ARZ3NDEKTSV4RRFFQ69G5FAV | 888ba555-4be6-4642-9415-a8ac1a98f206 |
3. 总结
由上表对比可知:
GUID v4 对于数据库索引的支持并不友好,在数据量大的情况下可导致频繁的页分裂,从而导致数据库性能下降。
TMID、Snowflake Id、ULID 因其时间的有序性对数据库索引支持良好,但 Snowflake 因其位宽较小、不含随机数,导致其可用年限较短,且在高并发场景下在存在时间回拨问题。
ULID 拥有 80 位的随机数相对较为浪费,TMID 48 位随机数亦可支持单机每毫秒百万亿级的随机性。同时分别划拨了 16 位的序列号和 16 位的机器 Id,使其相对 ULID 更具可追溯性。TMID 使用 BASE64 编码表示,相比 ULID 的 BASE32 编码,压缩率更高,在数据传输方面也更具优势。
综上,TMID 更适合作为在高并发的分布式系统中的数据库主键。