概念
UUIDs (Universally Unique IDentifier),也稱為 GUIDs (Globally 唯一標識符)。一個 UUID 是 128 位長,並且可以保證空間和時間上的唯一性。
使用 UUID 的主要原因之一是無需集中的管理,並且 UUID 的生成算法要求它支持單台每秒超過百萬次的生成速率。
布局和字節順序
UUID 呈現的格式為:f81d4fae-7dec-11d0-a765-00a0c91e6bf6
字段 | 數據類型 | 字節 | 注釋 |
---|---|---|---|
time_low | unsigned 32 bit integer | 0-3 | 低域位整數時間戳 |
time_mid | unsigned 16 bit integer | 4-5 | 中間字段位整數時間戳 |
time_hi_and_version | unsigned 16 bit integer | 6-7 | 高場位整數時間戳 |
clock_seq_hi_and_reserved | unsigned 8 bit integer | 8 | 整數時鍾序列與多路復用 |
clock_seq_low | unsigned 8 bit integer | 9 | 低域位整數時鍾序列 |
node | unsigned 48 bit integer | 10-15 | 空間唯一位整數節點標識符 |
版本
版本號在時間戳的最高 4 位(time_hi_and_version 的 4-7 bit)
UUID 的變體規則如下
Msb0 | Msb1 | Msb2 | Msb3 | 版本 | 描述 |
---|---|---|---|---|---|
0 | 0 | 0 | 1 | v1 | 基於時間的版本 |
0 | 0 | 1 | 0 | v2 | DEC 安全版本 |
0 | 0 | 1 | 1 | v3 | 基於名稱的版本(本文件中規定使用 MD5 散列) |
0 | 1 | 0 | 0 | v4 | 隨機或偽隨機生成的版本 |
0 | 1 | 0 | 1 | v5 | 基於名稱的版本(本文件中規定使用 SHA-1 散列) |
版本更准確地說應該叫子類型,稱其為版本只是為了兼容性。
時間戳
時間戳是一個 60 位的值,一般使用 UTC 時間表示,如果沒有 UTC 時間可用本地時間,但是盡量不建議這樣做,因為本地時間要生成 UTC 時間需要額外的時區信息。
時間序列
時間序列用於幫助避免當時鍾向后設置時可能出現的重復或者節點 ID 改變。如果已知時鍾序列的先前值,則它智能遞增,否則它應該設置為隨機或者高質量的偽隨機值。類似地,如果節點 ID 發生變化(例如,因為網卡在機器間移動),需要重新設置時間序列。
對於 UUID 的版本 3 或 5,時鍾序列是 14 位根據名稱描述構造的值。
對於 UUID 的版本 4,時鍾序列是隨機或偽隨機的 14 位值。
節點
對於 UUID 的版本 1,節點字段包含一個 IEEE 802 MAC 地址,通常是主機地址。
對於 UUID 的版本 3 或 5,節點字段是 48 位根據名稱描述構造的值。
對於 UUID 的版本 4,節點字段是隨機或偽隨機生成 48 位值。
nil UUID
nil UUID 是 UUID 的特殊形式,是所有 128 位均設置為零。
順序 UUID
在數據庫中存儲,經常使用 UUID 作為主鍵,但是 UUID 有個致命缺陷,就是沒有順序。如果這種無順序的 ID 當作主鍵在數據庫中使用會嚴重影響數據庫的性能。
現在有很多框架使用的算法支持生成遞增的 UUID,例如 ABP 框架里的順序 ID 參考了 https://github.com/jhtodd/SequentialGuid/blob/master/SequentialGuid/Classes/SequentialGuid.cs,這個順序 ID 有個生成類型枚舉 SequentialGuidType
,SQL Server 使用 SequentialAtEnd
類型,因為 SQL Server 使用最低的有效 6 個字節來排序,其他大多數數據庫應該傳遞 SequentialAsString
或 SequentialAsBinary
。
UUID v1 也定義了基於時間的版本,但是該標准將時間戳拆分為幾塊,限制了其作為順序 ID 的用途。因此這種順序 UUID 與傳統的 UUID 標准不兼容。
這個算法使用了 6 個字節 48 bit 來表示時間戳,精確到毫秒,大概能使用 5900 年,對於一般的應用足夠了。
還有一個時間精度更高的實現方案:https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/blob/ebe011a6f1b2a2a9709fe558cfc7ed3215b55c37/src/EFCore.MySql/ValueGeneration/Internal/MySqlSequentialGuidValueGenerator.cs,時間戳占 8 字節,精度到 100 ns,但是這個實現里有一些位移操作符,還結合了 UUID 的變體版本號,沒有細看,猜測思路應該跟第一種順序 UUID 也類似。
參考