PHP高並發生成不重複唯一標識

2021-09-27 00:05:54 字數 2334 閱讀 1428

假設唯一標識為使用者id,當有3個使用者同時註冊,生成使用者id的時間完全相同,如何保證id的唯一性

網友們給出的方案很多,其中比較流行的方案如下所示:

md5(uniqid(md5(microtime(true)),true));
microtime( true ) - 返回unix紀元以來的當前時間,精確到最接近的微秒(1568049494.73)

md5 ( string $str [, bool $raw_output = false ] ) : string - 返回長度為32的原始十六進製制格式資料

md5 ( string $str [, bool $raw_output = true ] ) : string - 返回長度為16的原始二進位制格式資料

uniqid ([ string $prefix = "" [, bool $more_entropy = true ]] ) : string - 如果設定為 true,uniqid() 會在返回的字串結尾增加額外的熵(使用combined linear congruential generator), 使得唯一id更具唯一性

從上面幾個函式的功能來看,保證唯一性主要靠uniqid,接著看看該函式的原始碼:

php_function(uniqid)

else

return_str(uniqid);

}

uniqid 是由四個部分組成:

prefix - 呼叫者傳遞的字串引數

sec - 當前時鐘的秒

usec - 當前時鐘的微秒

php_combined_lcg - 使用線性同餘生成的乙個墒值,為0 ~ 1 之間的隨機數(如 0.12345678),由引數more_entropy決定是否生成

在高併發情況下,php1、php2、php3 在微秒級同時操作,sec、usec 均相同。當字首 prefix 也相同時,保證唯一性只能靠php_combined_lcg,原始碼:

/*

* combinedlcg() returns a pseudo random number in the range of (0, 1).

* the function combines two cgs with periods of

* 2^31 - 85 and 2^31 - 249. the period of this function

* is equal to the product of both primes.

*/#define modmult(a, b, c, m, s) q = s/a;s=b*(s-a*q)-c*q;if(s<0)s+=m

static void lcg_seed(void);

phpapi double php_combined_lcg(void) /*

modmult(53668, 40014, 12211, 2147483563l, lcg(s1));

modmult(52774, 40692, 3791, 2147483399l, lcg(s2));

z = lcg(s1) - lcg(s2);

if (z < 1)

return z * 4.656613e-10;

}/* }}} */

由上面的分析可以看出,如果我們單純使用 uniqid() 這個方法,不帶任何引數的情況下只能保證單個程序/執行緒,在微秒級以上(毫秒級)是唯一的。如果使用uniqid(string $prefix, true), 增加墒值使用乙個隨機的方式保證唯一性。但是由於線性同余是比較簡單的生成隨機數的演算法,隨機性不足,所以,更優的方式是讓 prefix 引數也不相同:

uniqid(mt_rand(), true)
其中 mt_rand() 生成隨機數使用 mersenne twister random number generator (梅森旋轉演算法),而不再是線性同餘,範圍為0 ~ 2147483647。換句話說,上面這個 id 由兩種隨機演算法 + 時間戳生成。基本上,這個演算法在很大程度上能保證唯一性了。如果需要固定位數的hash值,例如32位:

md5(uniqid(mt_rand(), true))
如果需要傳參,例如使用者使用手機號碼註冊,可以表示為:

<?php 

$phone = '18600000000';

// 長度40

$uid = sha1(md5(uniqid(mt_rand(), true)).$phone);

PHP uniqid 高並發生成不重複唯一ID

php uniqid 函式可用於生成不重複的唯一識別符號,該函式基於微秒級當前時間戳。在高併發或者間隔時長極短 如迴圈 的情況下,會出現大量重複資料。即使使用了第二個引數,也會重複,最好的方案是結合md5函式來生成唯一id。php uniqid 生成不重複唯一標識方法一 這種方法會產生大量的重複資料...

PHP uniqid 高並發生成不重複唯一ID

php uniqid 函式可用於生成不重複的唯一識別符號,該函式基於微秒級當前時間戳。在高併發或者間隔時長極短 如迴圈 的情況下,會出現大量重複資料。即使使用了第二個引數,也會重複,最好的方案是結合md5函式來生成唯一id。php uniqid 生成不重複唯一標識方法一 這種方法會產生大量的重複資料...

高並發生成唯一訂單號

最近開發一套會員系統,涉及到訂單號生成,在高並發條前提下,如何生成唯一的訂單號值得斟酌,我這裡提供一種較為可行的方案 public static string getorderidbyuuid 0 代表前面補充0 4 代表長度為4 d 代表引數為正數型 return time string.form...