一文解決PHP中生成隨機(jī)數(shù)遇到的重復(fù)問題
場景描述
項(xiàng)目開發(fā)中很多地方需要用到唯一編碼,比如說訂單、卡券、邀請碼等等。這些編號(hào)是需要嚴(yán)格保證唯一性的,因?yàn)槿绻到y(tǒng)中訂單的編號(hào)存在倆一模一樣的,那造成很多數(shù)據(jù)的錯(cuò)亂。實(shí)現(xiàn)唯一編碼的方式也是很多的,一般是通過底層的一些隨機(jī)函數(shù) mt_rand() uniqid()等等。
探索實(shí)現(xiàn)方式一
public static function uniqidNumberCode($length = 10) { $time = time() . ''; if ($length < 10) $length = 10; $string = ($time[0] + $time[1]) . substr($time, 2) . rand(0, 9); while (strlen($string) < $length) $string .= rand(0, 9); return $string; }
上面這個(gè)是用的三方包中的生成方式。參數(shù)中可以設(shè)置當(dāng)前生成的編號(hào)長度。以當(dāng)前時(shí)間的時(shí)間戳為基礎(chǔ)數(shù)據(jù),計(jì)算出10位隨機(jī)數(shù)字。當(dāng)我們單次去執(zhí)行的時(shí)候,生成的數(shù)據(jù)是非常正確的。
但是,當(dāng)我們需要批量的生成一堆的隨機(jī)編號(hào)的時(shí)候
可以發(fā)現(xiàn),以肉眼可見的速度出現(xiàn)了一堆的重復(fù)數(shù)據(jù)。
探索方式二
請教了一下chatgpt,讓它生成一個(gè)方法如下
function generateUniqueNumber($length = 10) { // 生成一個(gè)唯一標(biāo)識(shí)符 $uniqueId = uniqid(); // 移除標(biāo)識(shí)符中的前綴并截取前10位 $uniqueNumber = substr($uniqueId, strlen($uniqueId) - 10); return $uniqueNumber; }
還是測試一下批量生成的場景。
雖然生成的數(shù)據(jù)看著正確,但是數(shù)據(jù)格式不是怎么的讓人可以接受。還是希望生成10位純數(shù)字的。
探索方式三
再一次請教了一下chatgpt。
function generateUniqueNumber($length = 10) { // 獲取當(dāng)前時(shí)間戳 $timestamp = time(); // 生成一個(gè)隨機(jī)數(shù),確保足夠的隨機(jī)性 $randomNumber = mt_rand(100, 999); // 組合時(shí)間戳和隨機(jī)數(shù),并截取前10位 $uniqueNumber = substr($timestamp . $randomNumber, 0, 10); return $uniqueNumber; }
這下可好,生成的數(shù)據(jù)完全的毫無區(qū)別了。看來雖然gpt能幫助我們很多,但是選擇還是需要謹(jǐn)慎些。一些關(guān)鍵邏輯如果出現(xiàn)嚴(yán)重問題可是不太好交差的。
探索方式四
我們嘗試用php底層的生成隨機(jī)數(shù)的函數(shù) mt_rand() 對數(shù)據(jù)進(jìn)行生成。
function generateUniqueNumber($length = 10) { $uniqueNumber = mt_rand(1000,9999); return $uniqueNumber; }
發(fā)現(xiàn)在某些特殊的情況下還是會(huì)出現(xiàn)重復(fù)數(shù)據(jù)的可能。
探索實(shí)現(xiàn)方式二
//生成10位隨機(jī)數(shù) function generateUniqueNumber() { list($usec, $sec) = explode(' ', microtime()); $seed = (float) $sec + ((float) $usec * 100000); mt_srand($seed); return mt_rand(1000000000,9999999999); }
在mt_rand函數(shù)的基礎(chǔ)上,生成隨機(jī)數(shù)之前。對隨機(jī)數(shù)發(fā)生器的種子也用毫秒的值進(jìn)行重新生成。然后再將mt_rand函數(shù)的區(qū)間盡量去放大。
這樣基本可以滿足需求,但是卻是無法保證萬無一失。程序這東西嘛,保證數(shù)據(jù)準(zhǔn)確才是永遠(yuǎn)的追求。為了準(zhǔn)確,我又給數(shù)據(jù)庫的唯一編號(hào)字段加了唯一索引。這樣就在數(shù)據(jù)庫層面上保證了生成的編號(hào)肯定是唯一的。
當(dāng)然,如果在生成編號(hào)以后,程序再主動(dòng)去數(shù)據(jù)庫中查詢一遍字段是否存在,然后再執(zhí)行下面的業(yè)務(wù)這就更好了。
以上是整個(gè)分析過程,不足之處或者更好方案歡迎給我留言。
以上就是一文解決PHP中生成隨機(jī)數(shù)遇到的重復(fù)問題的詳細(xì)內(nèi)容,更多關(guān)于PHP中生成隨機(jī)數(shù)遇到重復(fù)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
php 調(diào)試?yán)鱠ebug_print_backtrace()
debug_print_backtrace() 是一個(gè)很低調(diào)的函數(shù),很少有人注意過它. 不過當(dāng)我對著一個(gè)對象調(diào)用另一個(gè)對象再調(diào)用其它的對象和文件中的一個(gè)函數(shù)出錯(cuò)時(shí),它正在一邊笑呢2012-07-07php項(xiàng)目中類的自動(dòng)加載實(shí)例講解
在本篇文章里小編給大家整理的是關(guān)于php項(xiàng)目中類的自動(dòng)加載的實(shí)例內(nèi)容以及相關(guān)代碼,需要的朋友們學(xué)習(xí)下。2019-09-09通過JavaScript或PHP檢測Android設(shè)備的代碼
在此列出一些能夠在iOS的最大競爭者——安卓(Android)系統(tǒng)的檢測方法。即通過JavaScript或PHP檢測Android設(shè)備,給大家提供參考。2011-03-03PHP常用開發(fā)函數(shù)解析之?dāng)?shù)組篇[未完結(jié)]
數(shù)組處理函數(shù)在PHP開發(fā)中非常常見,學(xué)習(xí)好數(shù)組處理函數(shù)至關(guān)重要.數(shù)組處理函數(shù)在實(shí)際應(yīng)用中涉及到:數(shù)組的創(chuàng)建,字符串于數(shù)組的相互轉(zhuǎn)換,數(shù)組轉(zhuǎn)XML,數(shù)組轉(zhuǎn)JSON.數(shù)組的檢測.數(shù)組的合并于分割.數(shù)組的數(shù)目.獲取數(shù)組中的所有值,獲取數(shù)組中的所有鍵值2012-07-07詳解PHP防止直接訪問.php 文件的實(shí)現(xiàn)方法
這篇文章主要介紹了詳解PHP防止直接訪問.php 文件的實(shí)現(xiàn)方法的相關(guān)資料,這里提供實(shí)現(xiàn)禁止直接訪問.php文件的實(shí)例,需要的朋友可以參考下2017-07-07PHP+Ajax實(shí)時(shí)自動(dòng)檢測是否聯(lián)網(wǎng)的方法
這篇文章主要介紹了PHP+Ajax實(shí)時(shí)自動(dòng)檢測是否聯(lián)網(wǎng)的方法,通過Ajax調(diào)用連接百度效果實(shí)現(xiàn)檢測網(wǎng)站是否聯(lián)網(wǎng)的功能,需要的朋友可以參考下2015-07-07php使用mysqli和pdo擴(kuò)展,測試對比連接mysql數(shù)據(jù)庫的效率完整示例
這篇文章主要介紹了php使用mysqli和pdo擴(kuò)展,測試對比連接mysql數(shù)據(jù)庫的效率,結(jié)合完整實(shí)例形式對比分析了php分別使用mysqli和pdo擴(kuò)展連接mysql數(shù)據(jù)庫的執(zhí)行時(shí)間,需要的朋友可以參考下2019-05-05