通用唯一识别码(,缩写:UUID)是用于计算机体系中以识别信息的一个128位标识符。
UUID按照標準方法生成時,在實際應用中具有唯一性,且不依赖中央机构的注册和分配。UUID重复的概率接近零,可以忽略不计。
因此,所有人都可以自行建立和使用UUID,而且幾乎可以確定其不會與既有的識別碼重複。也因為如此,在不同地方產生的UUID可以使用於同一個資料庫或同一個頻道中,而且幾乎不可能重複。
UUID的應用相當普遍,許多計算平台都提供了對於生成和解析UUID的支援。
历史
1990年代, UUID 原本是用于阿波羅電腦的网络计算系统,后被用于开放软件基金会的分散式運算環境。分散式運算環境UUID的初始设计基于网络计算系统UUID,其设计受 Domain/OS 中定义和使用的(64位)唯一标识符的启发,这是一个也由阿波羅電腦设计的操作系统。后来,Microsoft Windows平台采用分散式運算環境设计作为全局唯一标识符(GUID)。
2005年7月,RFC 4122 为 UUID 注册了一个 URN 命名空间,并制定了早期的规范。当 RFC 4122 作为互联网工程任务组标准发布时,国际电信联盟基于先前的标准和 RFC 4122 早期版本标准化了 UUID。
标准
UUID 由开放软件基金会标准化,作为分散式運算環境(DCE)的一部分。
UUID 被紀錄为 ISO/IEC 11578:1996 "Information technology – Open Systems Interconnection – Remote Procedure Call(RPC)" 和後來的 ITU-T Rec. X.667 | ISO / IEC 9834-8:2005 规范的一部份。
互联网工程任务组公布了标准 RFC 4122
格式
在其规范的文本表示中,UUID 的 16 个 8 位字节表示为 32 个十六进制数字,由连字符 '-' 分隔成五组顯示,形式為「8-4-4-4-12」总共 36 个字符(32 个十六进制数字和 4 个连字符)。
例如:
: 123e4567-e89b-12d3-a456-426655440000
: xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
四位数字 M表示 UUID 版本,数字 N的一至三个最高有效位表示 UUID 变体。在例子中,M 是 1 而且 N 是 a(10xx2),這意味着此 UUID 是「变体1」、「版本1」UUID;即基于时间的 DCE/RFC 4122 UUID。
规范的 8-4-4-4-12 格式字符串基于 UUID 的16个字节的“记录布局”:
这些字段对应于「版本1」和「版本2」(基于时间的)UUID中的字段,但是「8-4-4-4-12」的表示適用於所有UUID,即使对于生成方式不同的UUID也是如此。
RFC 4122 第 3 节要求以小写形式生成字符,同时对输入不区分大小写,尽管一些常用的实现违反了此规则。
Microsoft GUID有時會以大括号表示:
: {123e4567-e89b-12d3-a456-426655440000}
不应将此格式与“Windows注册表格式”相混淆,后者指的是大括号内的格式。
RFC 4122为UUID定义了统一资源名称(URN)命名空间。作为URN呈现的UUID如下:
: urn:uuid:123e4567-e89b-12d3-a456-426655440000
编码
UUID 的二进制编码因系统而异。UUID的变体1是目前世界最常見的UUID,完全以大端序(big-endian)二进制存储与传输 UUID 。
例如,00112233-4455-6677-8899-aabbccddeeff 编码为字节 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff。
其他系统,特别是 Microsoft 在其 COM/OLE 库中对 UUID 的字符串表示,使用混合端格式,其中 UUID 的前三组是小端序/小尾序(little-endian),后两组是 大端序/大尾序(big-endian)。
例如,00112233-4455-6677-8899-aabbccddeeff 编码为字节 33 22 11 00 55 44 77 66 88 99 aa bb cc dd ee ff。
变体
UUID的变体(variant)字段,占1到3位元。RFC 4122定义了4种变体:
- 变体 0 (最显著位为0,二進制為0xxx2,十六進制表示為016到716) 用于向后兼容已经过时的1988年开发的 Apollo 网络计算系统(NCS)1.5 UUID 格式。 前6字节是48比特时间戳(从1980年1月1日UTC开始的4微秒的滴答数),随后2个字节保留,再1个字节是地址族(address family,使用了0..13个情形),最后7个字节是主机ID。这类似于UUID的版本1.
- 变体 1 (二進制為10xx2,十六進制為816到b16),定义在RFC 4122/DCE 1.1 UUIDs, 或"Leach–Salz" UUID。它是按照大端序作为二进制存储与传输。
- 变体 2 (二進制為110x2,十六進制為c16或d16),RFC称“保留,微软公司向后兼容”。早期的Microsoft Windows平台的GUID使用该格式。和完全使用大端序的變體 1 不同,變體 2 其中一部份按照小端序作为二进制存储与传输。
- 形如111x2保留未使用。
目前的UUID規範使用變體1和2。在文字表示上,兩種變體只有代表變體的位元不同称GUID与UUID是同义词,如同RFC 4122中表示UUID「也被稱作GUID」。這些文件表明了雖然「GUID」最初指代微軟所使用的其中一種UUID變體,但現在已經成為UUID的另一個名稱,含括變體1和2。
版本
对于「变体(variants)1」和「变体2」,标准中定义了五个版本(versions),并且在特定用例中某些版本可能比其他版本更合适。
版本由字符串中的 M 指示。
版本1的UUID是根据时间和节点ID(通常是MAC地址)生成;版本2的UUID是根据标识符(通常是组或用户ID)、时间和节点ID生成;版本3、版本5透過對命名空间(namespace)标识符和名称進行雜湊生成確定性的UUID;版本4的UUID則使用随机性或伪随机性生成。
Nil UUID
Nil UUID是一个特例,值为 ;也就是说,所有位都设置为 0。
版本1(日期时间和MAC地址)
版本1的UUID,是根据 60-bit 的时间戳和节点(生成UUID的计算机)的48-bit MAC地址而生成的。
时间戳的是这样计算的:自公曆首次於天主教會和教皇國以外的地方使用的日期,也就是协调世界时(UTC)1582年10月15日午夜算起,每經過100納秒時間戳加1。RFC 4122声明时间值在公元3400年左右算術溢位。
13-bit 或 14-bit「无统一」(uniquifying)时钟序列扩展了时间戳,以便处理处理器时钟不能足够快地前进的情况,或者每个节点有多个处理器和 UUID 生成器的情况。对于每个「版本1」UUID 对应于空间(节点)和时间(间隔和时钟序列)中的单个点,两个正确生成的「版本1」UUID 无意中相同的可能性实际上为零。由于时间和时钟序列总共74位,每个节点 id 可以生成 2^{74}(1.8\times10^{22} 或 18 sextillion)個「版本1」UUID,每个节点 id 的最大平均速率为每秒 1630 亿。基于网卡MAC地址的「版本1」和「版本2」UUID 的唯一性还取决于网卡制造商正确地为其卡分配唯一的MAC地址,这与其他制造过程一样容易出错。此外,某些作業系統允許終端用戶自訂MAC地址,例如OpenWRT。
使用节点的网络MAC地址作为节点ID,代表可以透過版本1的UUID逆向找到创建它的计算机。透過在檔案中嵌入UUID,可以實現追蹤到創建或修改這些檔案的計算機。在定位 Melissa 病毒的创建者时就使用了这个隐私漏洞。
如果节点没有或不希望暴露MAC地址,RFC 4122 确实允许「版本1」(或2)UUID 中的 MAC 地址被随机的48位节点ID替换。在这种情况下,RFC要求节点ID的第一个八位字节的最低有效位应设置为1。
版本2(日期时间和MAC地址,DCE安全版本)
RFC 4122 保留了版本2的UUID用於“DCE security”;但並没有提供任何细节。因此,许多 UUID 实现省略了「版本2」。但是,「版本2」UUID 的规范由 DCE 1.1 身份验证和安全服务规范提供。因此,版本2可能不适合用于以节点、域或标识符在约7秒以上1次的速率下生成 UUID 的情况。
版本3和版本5(基于命名空间名称)
「版本3」和「版本5」的 UUID 透過雜湊(hashing)命名空间标识符和名称生成。版本3使用 MD5 作为-{zh-hans:散列算法; zh-hant:雜湊演算法;}-,版本5則使用 SHA1。
例如,如果要有50%的機率至少發生一次衝突,需要生成至少 2.71 \times 10^{18}個版本4的UUID,计算如下:
n \approx \frac{1}{2} + \sqrt{\frac{1}{4} + 2 \times \ln(2) \times 2^{122} } \approx 2.71 \times 10^{18}
这个数字相当于每秒产生 10 亿个 UUID 持續 85 年。每个 UUID 長度為 16 字节,这么多 UUID 的文件大小約為 45 艾字节(EB),比目前存在的最大数据库大很多倍,它们都在数百PB的数量级。
若要使發生衝突的機率為p,至少必須生成多少個版本4的UUID可由下式近似计算:
\sqrt{2 \times 2^{122} \times \ln\frac{1}{1-p}}
因此,在 103 万亿个版本4 UUID 中找到重复的概率是 {1 \over 1000000000}(十亿分之一)。
使用
檔案系統
重要用途包括 ext2/ext3/ext4 文件系统用户空间工具(e2fsprogs 使用 util-linux 提供的 libuuid)、LUKS 加密分区、GNOME、KDE 和 Mac OS X,其中大部分源自 曹子德(Theodore Ts'o)的实现。
Solaris 中 UUID 的一种用途(使用開放軟體基金會的实现)是识别正在运行的操作系统实例,以便在内核崩溃的情况下将故障转储数据与故障管理事件配对。
分區標籤和分區UUID都儲存於超區塊中。兩者皆為檔案系統的一部份,而不是分區的一部份。例如,ext2-ext4包含UUID,而NTFS或FAT32則沒有。
超區塊是檔案系統的一部份,因此被完全包含在分區中,因此如果你執行,sda1和sdb1都會擁有相同的標籤和UUID。
COM
Microsoft的组件对象模型(COM)中使用了几种GUID :
- IID - 接口标识符;(在系统上注册的接口标识符存储在Windows注册表中的)
- CLSID - 类标识符;(存储在)
- LIBID - 类型库标识符;(存储于)
- CATID - 类别标识符;(它在一个类中的存在将其识别为属于某些类别类别,列於)
作为数据库主键
UUID 通常用作数据库表中的唯一键。
Microsoft SQL Server 版本4 Transact-SQL 中的 NEWID 函数會返回标准随机版本4的UUID,而 NEWSEQUENTIALID 函数返回类似于 UUID 的 128 位标识符,这些 UUID 會依序遞增,直到下次系统重啟。
另一方面,尽管名称如此,但 Oracle Database SYS_GUID 函数不会返回标准 GUID;相反,它根据主机标识符和进程或线程标识符返回一个16字节的 128 位 RAW 值,有点类似于 GUID。
PostgreSQL 包含一个 UUID 数据类型,并且可以通过使用模块中的函数生成大多数版本的UUID。
MySQL 提供了一个 UUID 函数,它生成标准的版本1 UUID。
当 UUID 用作主键时,版本3、4和5 UUID 的随机性以及 版本1和2 UUID 内的字段的排序可能会产生数据库定位或性能问题。例如,2002年 Jimmy Nilsson 报告说,当用作主键的版本4 UUID 被修改为包含基于系统时间的非随机后缀时,Microsoft SQL Server的性能显着提高。Nilsson 承认,这种所谓的“COMB”(组合时间和GUID)方法使UUID非标准并且更有可能被复制,但 Nilsson 仅要求在应用程序中的唯一性。透過重新排序和編碼版本1和版本2的UUID,將時間戳放在最前面,可以避免插入所造成的性能損失。
諸如Laravel這樣的部分網路框架支援「時間戳優先」的UUID,可以將UUID有效儲存於索引資料庫中。這種UUID是版本4格式的COMB UUID,但其中前48位元組成了一個時間戳,就像版本1的UUID一樣。其他基於COMB UUID概念的指定格式包括:
- ULID,其拋棄了用於表示版本4的4位元,並且預設使用base32編碼。
- UUID版本6到8是三種COMB UUID格式的正式提議。
参见
- 全局唯一标识符(GUID)
参考文献
评论 (0)