最近使用到了 uniqid,就產生了疑問?uniqid 生成的 id 由什麼組成?真的是惟一的麼?什麼狀況下會產生衝突?php
從文檔中看到 uniqid 函數有兩個參數算法
看源碼:dom
PHP_FUNCTION(uniqid) { ... gettimeofday((struct timeval *) &tv, (struct timezone *) NULL); sec = (int) tv.tv_sec; usec = (int) (tv.tv_usec % 0x100000); ... if (more_entropy) { uniqid = strpprintf(0, "%s%08x%05x%.8F", prefix, sec, usec, php_combined_lcg() * 10); } else { uniqid = strpprintf(0, "%s%08x%05x", prefix, sec, usec); } RETURN_STR(uniqid); }
基本就瞭解清楚了。uniqid 是由四個部分組成:函數
prefix + sec + usec + 「.」 + php_combined_lcg
其中 prefix 就是 uniqid 函數的第一個參數。它是一個字符串,傳遞進來什麼,就直接返回什麼。ui
sec 是當前時鐘的秒,usec 是毫秒,這兩個值都是從 gettimeofday 獲取的。換句話說,只要在一臺機器上,兩個 php 程序在同一個毫秒內獲取的 sec 和 usec 是同樣的。spa
php_combined_lcg 是 uniqid 的第二個參數決定的,它是一個墒值,它是使用線性同餘生成一個 0 ~ 1 之間的隨機數。若是第二個參數爲 true,就有這個值,若是第二個參數爲 false,就沒有這個值。code
好比:blog
➜ ~ php -r 'echo uniqid("my_", true);' my_5afe9b414c2141.76621929
因此說,若是咱們單純使用 uniqid() 這個方法,不帶任何參數的話,這個方法只能保證單個進程,在同一個毫秒內是惟一的。若是使用uniqid("", true)。 帶了一個墒值,自身已經有一個隨機的方式能保證生成的id的隨機性了。可是因爲線性同餘是比較簡單的生成隨機數的算法,隨機性有可能還不夠,因此,網上流傳的一種更隨機數值的方式是:進程
uniqid(mt_rand(), true)
其中 mt_rand() 生成隨機數就不是使用線性同餘生成隨機數的方式了,而是使用 Mersenne Twister Random Number Generator (梅森旋轉算法)。換句話說,上面這個 id 由兩種隨機算法 + 時間戳生成。基本上,這個算法在很大程度上能保證惟一性了(若是要問衝突率的話,估計只有數學系學生能研究出來了...)。md5
上面的這個給出的id會有一個點號,並且長度並非128bit。若是但願生成uuid,就須要一個hash,無論是md5,sha1 都是能夠選擇的。因此網上又有一種生成惟一碼的方式。
md5(uniqid(mt_rand(), true))
可是,本質上,這兩種方式的隨機性是相等的。
md5(uniqid(mt_rand(), true))--------親證這個效果好,不會重,就是沒規律----我本身的話