生成按時間增長的全域性唯一主鍵

crazyly 發表於2019-10-09

生成按時間增長的全域性唯一主鍵

方案一、生成按時間增長的全域性唯一主鍵 用來生成按時間增長的全域性唯一主鍵。這類主鍵的作用主要是在分散式環境中保證每條資料能夠有一個唯一標識,同時又有一定的自增長性以提高索引效率。當然也可以用來掩人耳目,畢竟一個簡單的int型別的自增ID的話,很容易讓人猜到你的資料量有多少了。 分散式環境下資料主鍵的生成方法其實是蠻多的,比如使用Mysql之類的自增ID,只需要設定好自增步長和起始值就可以滿足基本要求了,還有像目前流行的文件型資料庫MongoDB就提供了一個MongoId的實現,可以在客戶端直接生成長度為24的自增長型全域性字串主鍵。今天寫的這個PHP函式就是參考MongoId的演算法實現的,不需要安裝MongoDB擴充套件也可以使用。 MongoDB的PHP擴充套件中有一個C語言版本的 generate_id 函式的實現,MongoId 具有 12 個位元組(使它的字串形式是 24 個十六進位制字元),前四個位元組是一個時間戳(timestamp int,單位為秒),後三個是客戶端主機名的 hash 摘要,然後兩個是執行指令碼的程式 ID, 最後三位是一個以隨機數作為起始值的自增值。從這個描述裡我們也可以看出,MongoId的生成基本是向上增長的,也不太可能出現重複,是一個比較優質的主鍵生成實現。 eg:

function generate_id_hex()
{
    static $i = 0;
    $i OR $i = mt_rand(1, 0x7FFFFF);

    return sprintf("%08x%06x%04x%06x",
        /* 4-byte value representing the seconds since the Unix epoch. */
        time() & 0xFFFFFFFF,

        /* 3-byte machine identifier.
         *
         * On windows, the max length is 256. Linux doesn't have a limit, but it
         * will fill in the first 256 chars of hostname even if the actual
         * hostname is longer. 
         *
         * From the GNU manual:
         * gethostname stores the beginning of the host name in name even if the
         * host name won't entirely fit. For some purposes, a truncated host name
         * is good enough. If it is, you can ignore the error code.
         *
         * crc32 will be better than Times33. */
        crc32(substr((string)gethostname(), 0, 256)) >> 8 & 0xFFFFFF,

        /* 2-byte process id. */
        getmypid() & 0xFFFF,

        /* 3-byte counter, starting with a random value. */
        $i = $i > 0xFFFFFE ? 1 : $i + 1
    );
}

for ($j=0; $j <100 ; $j++) { 
    echo generate_id_hex();
    echo "<br>";
    # code...
}
exit;

方案二、PHP7下可以使用 random_bytes()函式

function getGenerateId ($len = 12) {

      $temp = random_bytes($len);

      return bin2hex($temp);
}

方案三、使用mongo 擴充套件 new \MongoDB\BSON\ObjectID()

當你的才華撐不起你的野心,那就靜下來學習