UUID

一種軟體建構的標準

UUID 是 通用唯一識別碼(Universally Unique Identifier)的縮寫,是一種軟體建構的標準,亦為開放軟體基金會組織在分散式計算環境領域的一部分。其目的,是讓分散式系統中的所有元素,都能有唯一的辨識信息,而不需要通過中央控制端來做辨識信息的指定。如此一來,每個人都可以創建不與其它人衝突的UUID。在這樣的情況下,就不需考慮資料庫創建時的名稱重複問題。

目前最廣泛應用的UUID,是微軟公司的全局唯一標識符(GUID),而其他重要的應用,則有Linux ext2/ext3文件系統、LUKS加密分區、GNOME、KDEMac OS X等等。另外我們也可以在e2fsprogs包中的UUID庫找到實現。

簡介


定義

UUID是國際標準化組織(ISO)提出的一個概念。UUID是一個128比特的數值,這個數值可以通過一定的演演算法計算出來。為了提高效率,常用的UUID可縮短至16位。UUID用來識別屬性類型,在所有空間和時間上被視為唯一的標識。一般來說,可以保證這個值是真正唯一的任何地方產生的任意一個UUID都不會有相同的值。使用UUID的一個好處是可以為新的服務創建新的標識符。這樣一來,客戶端在查找一個服務時,只需要在它的服務查找請求中指出與某類服務(或某個特定服務)有關的UUID,如果服務的提供者能將可用的服務與這個UUID相匹配,就返回一個響應。
UUID是基於當前時間、計數器(counter)和硬體標識(通常為無線網卡的MAC地址)等數據計算生成的。UUID可以被任何人獨立創建,並按需發布。UUID沒有集中管理機構,因為它們是不會被複制的獨特標識符。屬性協議允許設備使用UUID識別屬性類型,從而不需要用讀/寫請求來識別它們的本地句柄。

組成

UUID是指在一台機器上生成的數字,它保證對在同一時空中的所有機器都是唯一的。通常平台會提供生成的API。按照開放軟體基金會(OSF)制定的標準計算,用到了乙太網卡地址、納秒級時間、晶元ID碼和隨機數。
UUID由以下幾部分的組合:
(1)當前日期和時間,UUID的第一個部分與時間有關,如果你在生成一個UUID之後,過幾秒又生成一個UUID,則第一個部分不同,其餘相同。
(2)時鐘序列。
(3)全局唯一的IEEE機器識別號,如果有網卡,從網卡MAC地址獲得,沒有網卡以其他方式獲得。
UUID的唯一缺陷在於生成的結果串會比較長。關於UUID這個標準使用最普遍的是微軟的GUID(Globals Unique Identifiers)。在ColdFusion中可以用CreateUUID()函數很簡單地生成UUID,其格式為:xxxxxxxx-xxxx- xxxx-xxxxxxxxxxxxxxxx(8-4-4-16),其中每個 x 是 0-9 或 a-f 範圍內的一個十六進位的數字。而標準的UUID格式為:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12),可以從cflib 下載CreateGUID() UDF進行轉換。
(4)在hibernateJava orm框架)中,採用 IP-JVM啟動時間-當前時間右移32位-當前時間-內部計數(8-8-4-8-4)來組成UUID

作用


UUID 的目的是讓分散式系統中的所有元素,都能有唯一的辨識資訊,而不需要透過中央控制端來做辨識資訊的指定。如此一來,每個人都可以建立不與其它人衝突的 UUID。在這樣的情況下,就不需考慮資料庫建立時的名稱重複問題。目前最廣泛應用的 UUID,即是微軟的 Microsoft's Globally Unique Identifiers (GUIDs),而其他重要的應用,則有 Linux ext2/ext3 檔案系統、LUKS 加密分割區、GNOME、KDE、Mac OS X 等等。

重複機率


隨機產生的UUID(例如說由java.util.UUID類別產生的)的128個比特中,有122個比特是隨機產生,4個比特在此版本('Randomly generated UUID')被使用,還有2個在其變體('Leach-Salz')中被使用。利用生日悖論,可計算出兩筆UUID擁有相同值的機率約為:
以下是以x=2^122計算出UUID后產生碰撞的機率:
n機率
2^364 x 10^-16
2^414 x 10^-13
2^464 x 10^-10
與被隕石擊中的機率比較的話,已知一個人每年被隕石擊中的機率估計為170億分之1,也就是說機率大約是0.00000000006 (6 x 10^-11),等同於在一年內置立數十兆筆GUID併發生一次重複。換句話說,每秒產生10億筆UUID,100年後只產生一次重複的機率是50%。如果地球上每個人都各有6億筆GUID,發生一次重複的機率是50%。
產生重複GUID並造成錯誤的情況非常低,是故大可不必考慮此問題。
機率也與隨機數產生器的質量有關。若要避免重複機率提高,必須要使用基於密碼學上的假隨機數產生器來生成值才行。

版本


UUID具有多個版本,每個版本的演演算法不同,應用範圍也不同。首先是一個特例--Nil UUID--通常我們不會用到它,它是由全為0的數字組成:00000000-0000-0000-0000-000000000000

基於時間

基於時間的UUID通過計算當前時間戳、隨機數和機器MAC地址得到。由於在演演算法中使用了MAC地址,這個版本的UUID可以保證在全球範圍的唯一性。但與此同時,使用MAC地址會帶來安全性問題,這就是這個版本UUID受到批評的地方。如果應用只是在區域網中使用,也可以使用退化的演演算法,以IP地址來代替MAC地址--Java的UUID往往是這樣實現的(當然也考慮了獲取MAC的難度)。

DCE安全

DCE(Distributed Computing Environment)安全的UUID和基於時間的UUID演演算法相同,但會把時間戳的前4位置換為POSIX的UID或GID。這個版本的UUID在實際中較少用到。

MD5

基於名字的UUID通過計算名字和名字空間的MD5散列值得到。這個版本的UUID保證了:相同名字空間中不同名字生成的UUID的唯一性;不同名字空間中的UUID的唯一性;相同名字空間中相同名字的UUID重複生成是相同的。

隨機

根據隨機數,或者偽隨機數生成UUID。這種UUID產生重複的概率是可以計算出來的,但隨機的東西就像是買彩票:你指望它發財是不可能的,但狗屎運通常會在不經意中到來。

SHA1

和基於名字的UUID演演算法類似,只是散列值計算使用SHA1(Secure Hash Algorithm 1)演演算法。

應用


使用UUID的好處在分散式的軟體系統中(比如:DCE/RPC, COM+,CORBA)就能體現出來,它能保證每個節點所生成的標識都不會重複,並且隨著WEB服務等整合技術的發展,UUID的優勢將更加明顯。根據使用的特定機制,UUID不僅需要保證是彼此不相同的,或者最少也是與公元3400年之前其他任何生成的通用唯一標識符有非常大的區別。UUID最少在3000+年內不會重複。
通用唯一標識符還可以用來指向大多數的可能的物體。微軟和其他一些軟體公司都傾向使用全球唯一標識符(GUID),這也是通用唯一標識符的一種類型,可用來指向組建對象模塊對象和其他的軟體組件。第一個通用唯一標識符是在網路計算機系統(NCS)中創建,並且隨後成為開放軟體基金會(OSF)的分散式計算環境(DCE)的組件。

編碼規則


UUID(Universally Unique Identifier)全局唯一標識符,定義為一個字元串主鍵,採用32位數字組成,編碼採用16進位,定義了在時間和空間都完全惟一的系統信息。
UUID的編碼規則:
1)1~8位採用系統時間,在系統時間上精確到毫秒級保證時間上的惟一性;
2)9~16位採用底層的IP地址,在伺服器集群中的惟一性;
3)17~24位採用當前對象的HashCode值,在一個內部對象上的惟一性;
4)25~32位採用調用方法的一個隨機數,在一個對象內的毫秒級的惟一性。
通過以上4種策略可以保證惟一性。在系統中需要用到隨機數的地方都可以考慮採用UUID演演算法。