Universally Unique Identifier 通用唯一识别码
是 ISO/IEC 标准,也定义在 IETF 的 RFC4122 中。
128 位,也就是 16 字节,通常使用 32 位 16 进制数字,以 8-4-4-4-12
的形式表示,例如:d09abf7e-3e39-11ec-9dbc-b1755772e461
历史
- 阿波罗电脑公司 Apollo 的网络计算系统 NCS
- 开放软件基金会 OSF 的 DCE 系统(分布式计算环境)
- 微软 GUID 采用 DEC 的设计
- 互联网工程任务组 IETF 发布 RFC 4122,
同时,国际标准化组织 ISO 和国际电信联盟 ITU 也对其进行了标准化。
语法
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
M 表示版本,N 的一到三个最高有效位表示变体类型。
变体
- 变体 0:
0
(0 - 7) 早期,Apollo 网络计算系统使用的版本。
6 字节时间戳,2 字节保留,1 字节地址族,7 字节主机 ID
时间戳是从 1980 开始的四位微秒格式
由于最早的设计地址族只定义了 0 - 13,标准化之后,用最高位是不是 0 来区分
- 变体 1:
10
(8 - b) 这就是标准所采用的风格 - 变体 2:
110
(c, d) 微软 GUID,和变体 1 唯一的区别就是从大端序变成小端序
PS: 事实上,微软 GUID 后来也改成变体 1 了 - 变体 3:
111
(e, f) 保留
PS: 后面都当成是变体 1。
版本
-
Nil UUID,一个特例:
00000000-0000-0000-0000-000000000000
-
UUID1 48bit Mac 地址 + 60bit 时间戳
布局:- 时间戳低位 32bits
- 时间戳中间 16bits
- 4bits 版本 + 时间戳高位 12bits
- 2bits 变体类型 + 14bits 随机数
- 机器 ID 48bits
时间戳的计算方法:从公历开始采用的时间 1582-10-15 00:00:00 开始,以 100 纳秒(0.1 微秒)作为间隔。Python UUID 标准库关于这一部分的实现:
nanoseconds = time.time_ns() # 0x01b21dd213814000 is the number of 100-ns intervals between the # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00. timestamp = nanoseconds // 100 + 0x01b21dd213814000
-
UUID2
定义在 DCE, RFC4122 保留了这一部分,但是没有包含实现细节
> “版本 2” UUID 类似于“版本 1”,除了时钟序列的最低有效 8 bits 被“本地域(local domain)”号替换,并且时间戳的最低有效 32 bits 由在指定本地域内有意义的整数标识符替换。在 POSIX 系统上,本地域号 0 和 1 分别用于用户 ID(UIDs)和组 ID(GIDs),其他本地域号用于站点定义。在非 POSIX 系统上,所有本地域号都是站点定义的。 - UUID3 命名空间 + 名称
命名空间是一个 UUID
MD5(命名空间 + 名称), 然后替换版本和变体类型相关的位
UUID3 定义了以下几个命名空间:- 统一资源定位符 URL
6ba7b811-9dad-11d1-80b4-00c04fd430c8
- 域名
6ba7b810-9dad-11d1-80b4-00c04fd430c8
- 对象标识符
6ba7b812-9dad-11d1-80b4-00c04fd430c8
- X.500 轻型目录访问协议 LDAP
6ba7b814-9dad-11d1-80b4-00c04fd430c8
- 统一资源定位符 URL
- UUID4 随机 UUID,除了版本和变体类型信息
- 因此,第 14 位一定为 4,第 19 位一定为 89ab 中的一个(10xx)
- UUID5 和 UUID3 类似,不过 MD5 换成 SHA1