UUID 全稱 Universally Unique Identifier,即通用唯一識別碼。
0x01 版本#
UUID 是有不同的版本的,每個版本有不同的適用場景,比如,版本 4 建議使用隨機方式生成所有的可變因子。在很多場景下,這個其實是一個非常方便的實現方式。版本 1 使用的是 時間戳+時鐘序列+節點信息(機器信息)在一些分佈式系統場景下是能嚴格保證全局唯一的。twitter 的 snowflake 可以看作是是 UUID 版本 1 的簡化版。
到現在為止,UUID 一共有 5 個實現版本:
- 版本 1: 嚴格按照 UUID 定義的每個字段的意義來實現,使用的變量因子是時間戳+時鐘序列+節點信息(Mac 地址)
- 版本 2: 基本和版本 1 一致,但是它主要是和 DCE( IBM 的一套分佈式計算環境)。但是這個版本在 ietf 中也沒有具體描述,反而在 DCE 1.1: Authentication and Security Services 這篇文檔中說到了具體實現。所以這個版本現在很少使用到,並且很多地方的實現也都忽略了它。
- 版本 3: 基於 name 和 namespace 的 hash 實現變量因子,版本 3 使用的是 md5 進行 hash 算法。
- 版本 4: 使用隨機或者偽隨機實現變量因子。
- 版本 5: 基於 name 和 namespace 的 hash 實現變量因子,版本 5 使用的是 sha1 進行 hash 算法。
不管是 UUID 的哪個版本,它的結構都是一樣的,這個結構是按照版本 1 進行定義的,只是在其他版本中,版本 1 中的幾個變量因子都進行了變化。
0x02 基本結構#
UUID 長度是 128bit(16 字節(128 位)),換算為 16 進制數值 (每 4 位代表一個數值) 就是有 32 個 16 進制數值組成,中間使用 4 個 - 進行分隔,按照 8-4-4-4-12 的順序進行分隔。加上中間的橫杆,UUID 有 36 個字符。比如:3e350a5c-222a-11eb-abef-0242ac110002。
UUID 的格式是這樣的:xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
N 那個位置,只會是 8,9,a,b
M 那個位置,代表版本號,由於 UUID 的標準實現有 5 個版本,所以只會是 1,2,3,4,5
壹 Timestamp - 時間戳#
Timestamp 是一個 60 bits 的無符號數。對於 version 為 1 的 UUID,它從 1582-10-15 00:00:000000000 起到當前 UTC 時間,每隔 100 納秒加一。對於無法獲取 UTC 時間的系統,由於獲取不到 UTC,那麼你可以統一採用 localtime。(實際上一個系統時區相同就可以了)。
有了時間戳之後,結構圖中的 time_low,time_mid,time_hi 就知道了。
time_low
是 timestamp 60bit 中的 0 ~ 31bit,共 32bit。
time_mid
是 timestamp 60bit 中的 32 ~ 47bit,共 16bit。
time_hi_and_version
這個字段的意思很明確,就是包含兩個部分,version 和 time_hi。version 佔用 bit 數為 4. 代表它最多可以支持 31 個版本。time_hi 就是 timestamp 剩餘的 12bit,一共是 16bit。
貳 Clock Sequence - 時鐘序列#
如果計算 UUID 的機器進行了時間調整,或者是 nodeId 變化了(主機更換網卡),和其他的機器衝突了。那麼這個時候,就需要有個變量因子進行變化來保證再次生成的 UUID 的唯一性。
其實 Clock Sequence 的變化算法很簡單,當時間調整,或者 nodeId 變化的時候,直接使用一個隨機數,或者,在原先的 Clock Sequence 值上面自增加一也是可以的。
Clock Sequence 一共是 14bit
clock_seq_low
是 Clock Sequence 中的 0 ~ 7 bit 共 8bit。
clock_seq_hi_and_reserved
包含兩個部分,reserved 和 clock_seq_hi。其中 clock_seq_hi 為 Clock Sequence 中的 8 ~ 13 bit 共 6 個 bit,reserved 是 2bit,reserved 一般設置為 10。
叁 node - 節點信息#
Node 是一個 48 bits 的無符號數,對於 version 為 1 的 UUID,它選取 IEEE 802 MAC 地址,即網卡的 MAC 地址。當系統有多塊網卡時,任何一塊有效的網卡都可被做 Node 數據;對於沒有網卡的系統,取值為隨機數。
0x03 不同版本區別#
以上內容已經把 UUID 的結構構成說明清楚了。基本上這個結構構成是 UUID version1 的定義。我們可以看到,它的變量因子包含 timestamp,clock sequence,node。但在不同版本中,這幾個變量因子的含義是不同的。
在 version4 中,timestamp,clock sequence, node 都是隨機或者偽隨機的。
但在 version3 和 5 中,是基於 name 和 namesapc 的 hash 算法生成。
其中的 name 和 namespace 基本上和我們很多語言的命名空間,類名一樣,它的基本要求就是,name + namespace 才是唯一確定 hash 串的標準。換句話說,一樣的 namespace + name 使用相同的 hash 算法(比如 version3 的 md5)
計算出來的結果必須是一樣的,但是不同的 namespace 中的同樣的 name 生成的結果是不一樣的。
version3 和 version5 中的三個變量因子都是由 hash 算法保證的,version3 是 md5, version5 是 sha1。
好了,這次教程就到這裡啦~如果我認為 Cloud Shell 體驗不錯的話,以後會繼續更新的鴨!如果您認為這篇文章對您有幫助,可以考慮一下贊助嗎?謝謝啦~