Java UUID ?
UUID的生成規則在上一篇已經說明過,那麼UUID確實也有可能重複的,原因在於演算法Hash中也是會有碰撞機會的,以Java UUID類別來看。
public static UUID randomUUID() {
SecureRandom ng=numberGenerator;
if(ng == null)
numberGenerator=ng=new SecureRandom();
byte[] randomBytes=new byte[16];
ng.nextBytes(randomBytes);
return new UUID(randomBytes);
}
在上面我們可以看到SecureRandom(強制隨機)的類別,官方文件說明:
Note:
Depending on the implementation,
the generateSeed and nextBytes methods may block as entropy is being gathered, for example,
if they need to read from /dev/random on various unix-like operating systems.
看樣子UUID的隨機數是有可能被用完的,但機會較小,然而我又去找了wiki說明
在UNIX作業系統(包括類UNIX系統)中,/dev/random是一個特殊的裝置檔案,可以用作亂數發生器或偽亂數發生器。
什麼是entropy
熵(entropy)是描述系統混亂無序程度的物理量,一個系統的熵越大則說明該系統的有序性越差,即不確定性越大。內核維護了一個熵池用來收集來自設備驅動程序和其它來源的環境噪音。
/dev/radom原理
發生器有一個容納噪聲資料的熵池(entropy pool),在讀取時,/dev/random
裝置會返回小於熵池噪聲總數的隨機位元組。/dev/random
可生成高隨機性的公鑰或一次性密碼本。若熵池空了,對/dev/random
的讀操作將會被阻塞,直到收集到了足夠的環境噪聲為止。這樣的設計使得/dev/random
是真正的亂數發生器,提供了最大可能的亂數據熵,建議在需要生成高強度的金鑰時使用。
/dev/uradom原理
/dev/random
的一個副本是/dev/urandom(「unblocked」,非阻塞的亂數發生器),它會重複使用熵池中的資料以產生偽亂數據。這表示對/dev/urandom
的讀取操作不會產生阻塞,但其輸出的熵可能小於/dev/random
的。它可以作為生成較低強度密碼的偽亂數生成器,不建議用於生成高強度長期密碼。
結論
林林總總的加起來,你會發現Java UUID除了會用完之外,還可能發生阻塞,我今天也可以修改JDK讓他跑/dev/uradom但是偽亂數並不是真正的隨機亂數。但,其實發生阻塞的機會,可能等到你有孫子了都還不太可能會發生,因此也不必過於擔心。