網上搜索,發現大體都類似如下:
<code> $chars = md5(uniqid(mt_rand(), true)); $uuid = substr($chars,0,8) . '-'; $uuid .= substr($chars,8,4) . '-'; $uuid .= substr($chars,12,4) . '-'; $uuid .= substr($chars,16,4) . '-'; $uuid .= substr($chars,20,12); return $prefix . $uuid;</code>
<code> mt_srand ( ( double ) microtime () * 10000 ); //optional for php 4.2.0 and up.随便数播种,4.2.0以后不需要了。 $charid = strtoupper ( md5 ( uniqid ( rand (), true ) ) ); //根据当前时间(微秒计)生成唯一id. $hyphen = chr ( 45 ); $uuid = '' . substr ( $charid, 0, 8 ) . $hyphen . substr ( $charid, 8, 4 ) . $hyphen . substr ( $charid, 12, 4 ) . $hyphen . substr ( $charid, 16, 4 ) . $hyphen . substr ( $charid, 20, 12 ); return $uuid;</code>
看了UUID的說明,怎麼感覺這些生成方法 撞擊率 達不到標準啊?
網上搜索,發現大體都類似如下:
<code> $chars = md5(uniqid(mt_rand(), true)); $uuid = substr($chars,0,8) . '-'; $uuid .= substr($chars,8,4) . '-'; $uuid .= substr($chars,12,4) . '-'; $uuid .= substr($chars,16,4) . '-'; $uuid .= substr($chars,20,12); return $prefix . $uuid;</code>
<code> mt_srand ( ( double ) microtime () * 10000 ); //optional for php 4.2.0 and up.随便数播种,4.2.0以后不需要了。 $charid = strtoupper ( md5 ( uniqid ( rand (), true ) ) ); //根据当前时间(微秒计)生成唯一id. $hyphen = chr ( 45 ); $uuid = '' . substr ( $charid, 0, 8 ) . $hyphen . substr ( $charid, 8, 4 ) . $hyphen . substr ( $charid, 12, 4 ) . $hyphen . substr ( $charid, 16, 4 ) . $hyphen . substr ( $charid, 20, 12 ); return $uuid;</code>
看了UUID的說明,怎麼感覺這些生成方法 撞擊率 達不到標準啊?
目前許多所謂PHP產生UUID的方法都以隨機數最為其演算法的基礎,這雖然在實務上很難出現重複的幾率,但在理論上顯然是行不通的。
這裡用MongoDb的ObjectId作為例子,個人覺得這種生成方法是可以引入到PHP的。
ObjectId主要分為四塊:時間戳記、毫秒數、機器碼、自增計數。
前兩者就不用細說了,PHP都可以取到,重點在後兩者上。
機器碼主要用於避免在不同主機間產生相同的UUID。
機器碼目前主要的生成方法是根據硬體資訊進行雜湊計算出,而這個方法並不適用於PHP。
主要因為兩點,一是PHP不能直接獲得硬體資訊(需要透過擴展或執行本地命令等方法),二是PHP請求與請求之間無法共享數據,所以每次請求都得拉取機器碼,對性能影響很大。
解決這一問題有個很簡單的辦法,就是在不同機器先計算出機器碼,之後直接寫入配置文件,PHP處理時直接讀取即可。
自增計數主要用於避免在並發處理中產生相同的UUID。
對於自增來說,PHP由於無法在請求間共享數據,所以無法直接實現自增計數。
解決這一問題我們可以引入PHP的兩個擴展,分別是Semaphore和Shared Memory,這兩者都在PHP源碼中集成,透過--enable-sysvsem和--enable-sysvshm就能打開。我們只需要把自增數放置在共享記憶體中,再透過信號量限制訪問,即可達到並發請求共享自增技術的目的了。當然,自增也能透過其他工具來實現。
Linux核心提供有UUID產生介面:cat /proc/sys/kernel/random/uuid
Linux上一切皆檔案,不管什麼程式,讀取檔案就能取得一個UUID.
自行產生一個唯一值:
<code>php best.php <?php echo uniqid(mt_rand().'_', true)."\n"; echo uniqid(mt_rand().'_', true)."\n"; //代码前后两次调用输出都不一样: 405797689_58295933a5de69.42485678 748054035_58295933a5e072.26553654 //如果运行时再加上远程用户地址/端口/进程PID的话,唯一性应该都已经够用了. echo uniqid($_SERVER['REMOTE_ADDR'].'_'.$_SERVER['REMOTE_PORT'].'_'.getmypid().'_'.mt_rand().'_', true)."\n"; echo uniqid($_SERVER['REMOTE_ADDR'].'_'.$_SERVER['REMOTE_PORT'].'_'.getmypid().'_'.mt_rand().'_', true)."\n";</code>
另外看似用openssl_random_pseudo_bytes
也能產生不錯的隨機字串:
<code>echo base64_encode(openssl_random_pseudo_bytes(32));</code>