PHP 如何產生 Unique ID

Unique ID 的做法有很多,重點是適用於何種狀況,主要的類型可區分

有規則的: 例如利用 MySQL 的 AUTO_INCREMENT,適用於平台內部非公開的key,或者公開但不敏感的資料,就算被User 猜中也沒關係的資料。

無規則的: 也就是真正的亂數,User 無法簡單猜到,適用於較敏感而且公開的資料,當然仍須防範User 使用暴力破解法,用程式不斷亂槍打鳥,最後仍有被猜中的風險。

以下介紹幾種製作 Unique ID 的做法

  1. Flicker 使用的方法 (有規則 / MySQL / 簡單效率好)
    參考網址:http://code.flickr.net/2010/02/08/ticket-servers-distributed-unique-primary-keys-on-the-cheap/

  2. 基於 Twitter Snowflake 演算法 (亂數 / 需安裝)
    參考網址:https://github.com/liexusong/ukey
    缺點:需安裝,非自有server無法安裝套件。

  3. PHP Function uniqid (亂數)
    缺點:大量執行緒下,可能產生重複的id, 第二個參數 more_entropy 設為 true 可產生格外的長度到 23 字元,更確保唯一性,但是網路上看過有說法表示,即便如此,仍有重複可能,只是重複機率極低而已。

  4. UUID (亂數)
    參考網址:https://github.com/lootils/uuid MySQL 也有 uuid function

  5. PHP Function shmop_open (有規則)
    利用記憶體共享,將最後一個序號記在記憶體中,每個執行緒來讀取後+1寫回
    缺點:僅適用短時間內,萬一重複也沒有問題的地方,因為Server restart後序號就會歸零重來。

  6. Hashids 第三方library (亂數 / 類似 youtube 影片參數)
    參考網址:http://hashids.org/php/
    沒有實測過,是否真的唯一,或者只是重複率低。

  7. 如何產生亂數8碼數字唯一ID? 只有8碼數字,理論上產生重複的機率是比較高的,目前並未看到網路介紹演算法能有效處理,因此在沒有更好的方式之前,我們可以使用亂數表來做。
    1. 建立表格
      CREATE TABLE `資料庫名稱`.`tickets` ( `id` INT UNSIGNED NOT NULL , `sid` VARCHAR(50) NOT NULL , PRIMARY KEY (`id`), INDEX (`sid`)) ENGINE = MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci
    2.  迴圈連續執行以下SQL到要的數量,例如 5 萬筆
      INSERT INTO tickets SET id=FLOOR(RAND() * (99999999-10000000+1)) + 10000000 ON DUPLICATE KEY UPDATE sid=tickets.sid
    3. 使用上面提到的製作UUID的方法,取得 $SID = 某UUID,然後執行
      UPDATE tickets SET sid='$SID' WHERE sid='' LIMIT 1
    4. 取回剛剛UUID 所 update row 的 id,就是我們要的唯一ID
      SELECT id FROM tickets WHERE sid='$SID' LIMIT 1