UUID那些事
UUID 是一個全局唯一的通用識別碼。它使用某種規則,而不是某種中心化的自增方式,來保證這個識別碼的全局唯一性。UUID 有非常多的使用場景,比如在分布式系統中,需要生成全局唯一 ID 來進行日志記錄。UUID 的生成規則由 rfc4122 來進行定義。
UUID 和 GUID 的區別
其實是沒有區別的,GUID 是微軟按照 UUID 的規則實現的一套方法。它本質的目的也是為了保證全局唯一性。微軟已經使用 GUID 在 Windows 的 COM,ActiveX 等技術上了。但是這里注意的一點是,UUID 本質是有多種版本的,GUID 也是在不同的使用場景實現的是不同的 UUID 版本,比如 COM 是使用 UUID 版本1 進行實現的。所以,在聊 UUID 和 GUID 是不是一樣的時候,附帶的信息應該了解清楚版本信息。
版本
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中的幾個變量因子都進行了變化。
UUID 基本結構
UUID 長度是128bit,換算為16進制數值(每4位代表一個數值)就是有32個16進制數值組成,中間使用4個-進行分隔,按照8-4-4-4-12的順序進行分隔。加上中間的橫桿,UUID有36個字符。
這個圖是 UUID 的具體結構。它的可變因子有三個,Timestamp 時間戳,Clock Sequence時鍾序列,node節點信息。然后由他們的不同部分組成這個 UUID。
Timestamp
時間戳是其中一個可變因子。時間戳有長度為 60bit。它代表現在當前UTC時間(必須使用UTC時間,這樣就統一了時區)和1582-10-15 00:00:000000000,每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 這個變量因子由MAC地址組成,通常是IP地址。它有48bit大小。其中的 0-15填入node(0-1)的位置,16-47填入node(2-5)的位置。
不同版本
基本上,按照上節說的已經把 UUID 的結構構成說明清楚了。基本上這個結構構成是 UUID version1 的定義。我們可以看到,它有的變量因子是 timestamp, clock sequence, node。
在不同版本中,這幾個變量因子的含義是不同的。
version4
在version4 中,timestamp,clock sequence, node都是隨機或者偽隨機的。
version3&5
version3和5 叫做基於 name 和 namesapce 的 hash 結構生成。其中的name 和namespace 基本上和我們很多語言的命名空間,類名一樣,它的基本要求就是,name + namespace 才是唯一確定hash串的標准。換句話說,一樣的namespace + name 使用的hash算法(比如version3的md5)計算出來的結果必須是一樣的,但是不同的 namespace 中的同樣的 name 生成的結果是不一樣的。
version3 和 version5 中的三個變量因子都是由hash 算法保證的,version3是 md5, version5是sha1。