1. 程式人生 > >UUID全域性唯一識別符號

UUID全域性唯一識別符號

UUID 是通用唯一識別碼(Universally Unique Identifier)的縮寫,是一種軟體建構的標準,亦為開放軟體基金會組織在分散式計算環境領域的一部分。 UUID 的目的是讓分散式系統中的所有元素,都能有唯一的辨識資訊,而不需要透過中央控制端來做辨識資訊的指定。如此一來,每個人都可以建立不與其它人衝突的 UUID。在這樣的情況下,就不需考慮資料庫建立時的名稱重複問題。 目前最廣泛應用的 UUID,即是微軟的 Microsoft's Globally Unique Identifiers (GUIDs),而其他重要的應用,則有 Linux ext2/ext3 檔案系統、LUKS 加密分割區、GNOME、KDE、Mac OS X 等等。
UUID是指在一臺機器上生成的數字,它保證對在同一時空中的所有機器都是唯一的。通常平臺會提供生成的API。按照開放軟體基金會(OSF)制定的標準計算,用到了乙太網卡地址、納秒級時間、晶片ID碼和許多可能的數字 UUID由以下幾部分的組合: (1)當前日期和時間,UUID的第一個部分與時間有關,如果你在生成一個UUID之後,過幾秒又生成一個UUID,則第一個部分不同,其餘相同。 (2)時鐘序列。 (3)全域性唯一的IEEE機器識別號,如果有網絡卡,從網絡卡MAC地址獲得,沒有網絡卡以其他方式獲得。 標準的UUID格式如下: 123e4567-e89b-12d3-a456-426655440000
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx 除連字元-外,上面每個字元都是一個十六進位制的數字,共有5個部分組成,第一部分8個,第二部分4個,第三部分4個,第四部分4個,第五部分12個,8-4-4-4-12,一共32個十六進位制字元,因此一共是128位,該結構中包含版本(Version)、變體 (Variant)、時間(Time)、時鐘序列(Clock Sequence)、節點(Note)資訊(以無符號整型值表示)。其中,M表示UUID的版本,N表示UUID的變體。
Name Length (Bytes) Length (Hex Digits) Contents
time_low 4 8 integer giving the low 32 bits of the time
time_mid 2 4 integer giving the middle 16 bits of the time
time_hi_and_version 2 4 4-bit "version" in the most significant bits, followed by the high 12 bits of the time
clock_seq_hi_and_res clock_seq_low 2 4 1-3 bit "variant" in the most significant bits, followed by the 13-15 bit clock sequence
node 6 12 the 48-bit node id
變體為了能相容過去的UUID,以及應對未來的變化,因此有了變體(Variants)這一概念。目前已知的變體有如下幾種: variant 0:N的格式為0xxx。為了向後相容預留。 variant 1:10xx。當前正在使用的。 variant 2:11xx。為早期微軟GUID預留。 variant 3:111x。為將來擴充套件預留。目前暫未使用。 版本: 版本用於定義UUID的形成方法,UUID的生成有時間、名稱、隨機數三種策略,以第9位元組(VersionAndTimeHigh)的最高4位表示,目前uuid定義有5個版本: Version 1:基於時間和MAC地址。由於使用了MAC地址,因此能夠確保全球唯一性,但是同時也暴露了MAC地址,私密性不夠好。 Version 2:DCE安全的UUIDDCE(Distributed Computing Environment)安全的UUID和基於時間的UUID演算法相同,但會把時間戳的前4位置換為POSIX的UID或GID。這個版本的UUID在實際中較少用到。 Version 3 :基於名字空間(MD5)。通過計算名字和名字空間的MD5雜湊值生成UUID。相同名字空間中不同名字生成的UUID的唯一性;不同名字空間中的UUID的唯一性;相同名字空間中相同名字的UUID重複生成是相同的。 Version 4 :基於隨機數或者偽隨機數。雖然是基於隨機數,但是重複的可能性可以忽略不計,因此該版本也是被經常使用的版本。 Version 5 : 基於名字空間(SHA1)。跟Version 3類似,但是雜湊函式使用了SHA1演算法。 從UUID的不同版本可以看出,Version 1/2適合應用於分散式計算環境下,具有高度的唯一性;Version 3/5適合於一定範圍內名字唯一,且需要或可能會重複生成UUID的環境下;至於Version 4,最好不用 時間戳時間是一個60位的整型值(除4位版本號外的前8位元組),對應UTC(格林尼治時間1582年10月15日午夜始)的100ns時間間隔計數。 對於ver 4和5,該值分別對應一個隨機數和一個全域性唯一的名稱。 時鐘序列: 對基於時間的UUID版本,時間序列用於避免因時間向後設定或節點值改變可能造成的UUID重複,對基於名稱或隨機數的版本同樣有用:目的都是為了防止UUID重複。如果前一時鐘序列已知,通過自增實現時鐘序列值的改變;否則,通過密碼學(偽)隨機數設定新的時鐘序列值。 節點: 對基於時間的UUID版本,節點由48位的單播MAC地址構成。對於沒有MAC地址的系統,節點值為一個密碼學(偽)隨機數(為防止與MAC地址發生碰撞,需設定多播位)。 這些欄位對應於版本1和2基於時間的UUIDs,但是相同的8-4-4-12表示用於所有的UUIDs,甚至對於構造不同的UUIDs也是如此。 微軟的guid有時會用周圍的括號來表示: {123e4567-e89b-12d3-a456-426655440000} 這種格式不應該與“登錄檔格式”混淆,“登錄檔格式”指的是花括號內的格式。 RFC 4122為UUIDs定義了一個統一的資源名稱(URN)名稱空間。 urn:uuid:123e4567-e89b-12d3-a456-426655440000 UUIDs的二進位制編碼在系統之間有所不同。許多系統完全以big-endian格式對UUID進行編碼。 例如,00112233-4455-6677-8899-aabbccddeeff被編碼為位元組,以位元組為單位,以位元組為單位,以位元組為單位,以位元組為單位。 其他系統,特別是微軟在他們的COM/OLE庫中對UUIDs進行編組,使用了一個混合的endian格式,其中前三個元件都是little-endian,最後兩個是big-endian。 例如,00112233-4455-6677-8899-aabbccddeeff被編碼為位元組33 22 11 00 5547,688-8899。 UUID是由一組32位數的16進位制數字所構成,是故UUID理論上的總數為16^32=2^128,約等於3.4 x 10^38。也就是說若每納秒產生1兆個UUID,要花100億年才會將所有UUID用完。 UUID的標準型式包含32個16進位制數字,以連字號分為五段,形式為8-4-4-4-12的32個字元。示例:
  • 550e8400-e29b-41d4-a716-446655440000
UUID亦可刻意重複以表示同類。例如說微軟COM中,所有元件皆必須實現出IUnknown介面,方法是產生一個代表IUnknown的UUID。無論是程式試圖訪問元件中的IUnknown介面,或是實現IUnknown介面的元件,只要IUnknown一被使用,皆會被參考至同一個ID:00000000-0000-0000-C000-000000000046。 隨機產生的UUID(例如說由java.util.UUID類別產生的)的128個位元中,有122個位元是隨機產生,4個位元在此版本('Randomly generated UUID')被使用,還有2個在其變體('Leach-Salz')中被使用。利用生日悖論,可計算出兩筆UUID擁有相同值的機率約為: 以下是以x=2^122計算出n筆GUID後產生碰撞的機率:
n 機率
68,719,476,736 = 2^36 0.0000000000000004 (4 x 10^-16)
2,199,023,255,552 = 2^41 0.0000000000004 (4 x 10^-13)
70,368,744,177,664 = 2^46 0.0000000004 (4 x 10^-10)
與被隕石擊中的機率比較的話,已知一個人每年被隕石擊中的機率估計為170億分之1,也就是說機率大約是0.00000000006 (6 x 10^-11),等同於在一年內建立數十兆筆GUID併發生一次重複。換句話說,每秒產生10億筆UUID,100年後只產生一次重複的機率是50%。如果地球上每個人都各有6億筆GUID,發生一次重複的機率是50%。 產生重複GUID並造成錯誤的情況非常低,是故大可不必考慮此問題。 機率也與隨機數產生器的質量有關。若要避免重複機率提高,必須要使用基於密碼學上的假隨機數產生器來生成值才行。