UUID是如何保證唯一性的?

我記得是根據硬體特徵,那麼,如果在虛擬機里呢?生成兩個完全相同的虛擬機,然後讓他們在同一時間生成UUID。。。會得到相同的UUID嗎?


首先,即便是虛擬機的話MAC地址也是不一樣的。另外你說的統一時間還是個宏觀的概念,這個僅僅是決定了UUID生產串中的某一部分相同而已,因為為了保證UUID的唯一性,規範定義了包括網卡MAC地址、時間戳、名字空間(Namespace)、隨機或偽隨機數、時序等元素。

當然,你要說UUID是不是絕對的不會出現重複的,這個也不能這樣說的(我下面會提到)。

UUID具有以下涵義:

經由一定的演算法機器生成

為了保證UUID的唯一性,規範定義了包括網卡MAC地址、時間戳、名字空間(Namespace)、隨機或偽隨機數、時序等元素,以及從這些元素生成UUID的演算法。UUID的複雜特性在保證了其唯一性的同時,意味著只能由計算機生成。

非人工指定,非人工識別

UUID是不能人工指定的,除非你冒著UUID重複的風險。UUID的複雜性決定了「一般人「不能直接從一個UUID知道哪個對象和它關聯。

在特定的範圍內重複的可能性極小

UUID的生成規範定義的演算法主要目的就是要保證其唯一性。但這個唯一性是有限的,只在特定的範圍內才能得到保證,這和UUID的類型有關(參見UUID的版本)。

UUID的版本

UUID具有多個版本,每個版本的演算法不同,應用範圍也不同。

首先是一個特例--Nil UUID--通常我們不會用到它,它是由全為0的數字組成,如下:

00000000-0000-0000-0000-000000000000

UUID Version 1:基於時間的UUID

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

UUID Version 2:DCE安全的UUID

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

UUID Version 3:基於名字的UUID(MD5)

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

UUID Version 4:隨機UUID

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

UUID Version 5:基於名字的UUID(SHA1)

和版本3的UUID演算法類似,只是散列值計算使用SHA1(Secure Hash Algorithm 1)演算法。

UUID的應用

從UUID的不同版本可以看出,

Version 1/2適合應用於分散式計算環境下,具有高度的唯一性;

Version 3/5適合於一定範圍內名字唯一,且需要或可能會重複生成UUID的環境下;

至於Version 4,個人的建議是最好不用(雖然它是最簡單最方便的)。

通常我們建議使用UUID來標識對象或持久化數據,但以下情況最好不使用UUID:

映射類型的對象。比如只有代碼及名稱的代碼表。

人工維護的非系統生成對象。比如系統中的部分基礎數據。

對於具有名稱不可重複的自然特性的對象,最好使用Version 3/5的UUID。比如系統中的用戶。如果用戶的UUID是Version 1的,如果你不小心刪除了再重建用戶,你會發現人還是那個人,用戶已經不是那個用戶了。(雖然標記為刪除狀態也是一種解決方案,但會帶來實現上的複雜性。)


只要保證不在同一台機器中開多個線程同時生成guid,就幾乎不會重複


上面的回答已經簡單明了,我補充個網站:UUID Online


不一定,你這種情況的衝突有一定程度取決於你所用的uuid版本和具體的實現,比如你用v3,這個版本一般用來解決命名空間的問題的,那麼即便你在不同時間不同物理機器用相同的名稱,也是會生成相同uuid的,相反如果用v4,而實現從/dev/random熵池取隨機數,那麼即便是嚴格上的「同一時間」生成,那麼也極可能不同。

題外話,理論上來說uuid是有衝突的可能的,因為總是有個128位的上限擺在那裡。但是要產生衝突的條件太極端以至於通常情況下不太可能。另外,即便有兩個相同的uuid,只要所應用到的上下文不一樣也不會產生問題。比如有兩個相同的uuid,一個是某商城訂單編號而另一個是com組件的標識符


不止依賴硬體信息,還有時間等很多因素。記得好像還有一個RFC描述UUID呢


uuid官方標準文檔

http://www.ietf.org/rfc/rfc4122.txt

UUID唯一資源命名空間的來龍去脈(RFC4122)


因為有限的時間內地球上硬體數量有限 所以在有限數量的硬體中uuid也是有限的,但也可能重複,比如同一個機器兩個線程同時生成uuid。

假如除去硬體標識只要uuid長度有限就可能會重複,除非uuid長度無限


ghost的win7 uuid會相同嗎 是不是高版本已經不會相同


去中心的生成方法本身沒法保證唯一性。一般降到實際可忽略的重複概率就能用了。


分享一個解決UUID的問題,一個實現 Twitter SnowFlake 演算法 的 Go 分散式 UID 生成器

GitHub - zheng-ji/goSnowFlake

根據 Twitter SnowFlake 演算法, 實現的分散式線程安全 UID 生成器


推薦閱讀:

程序員能20分鐘徒手寫出一個沒bug的快速排序嗎?(可以調試)
如何在最短的時間內搞定數據結構和演算法,應付面試?
如果按國家分,哪個國家編程最厲害?有沒有代表人物?
如何解釋召回率與準確率?
你有哪些時候能力突然增強?說明例子和進行原因分析?

TAG:軟體 | 演算法 | 計算機 | 計算機技術 |