在高並發請求下容易參數兩個問題
1.資料出錯,導致產品超賣。
2.頻繁操作資料庫,導致效能下降。
本文主要和大家詳細介紹了php處理搶購類功能的高並發請求,具有一定的參考價值,有興趣的小伙伴們可以參考一下,希望能幫助到大家。
測試環境
Windows7
apache2.4.9
php5.5.12
php框架yii2.0
工具apache bench(apache自帶高並發請求工具)。
通常處理方法
從控制器可以看出程式碼思路。先查詢商品庫存。若庫存大於0 ,則庫存減少1,同時生產訂單,輸入搶購者資料。
// 常规代码处理高并发 public function actionNormal(){ // 查询库存 $stock = Goods::find()->select('stock')->where(['goods_id'=>100001])->asArray()->one(); // 判断该商品是否还有库存 if ($stock['stock']>0) { // 库存减一 Goods::updateAllCounters(['stock' => -1],['goods_id'=>100001]); // 生产订单(另外功能,暂且随机赋值) $order = $this->build_order(); // 秒杀信息入库 $model = new Highly(); $model->order_id = $order; $model->goods_name = '秒杀商品'; $model->buy_time = date('Y-m-d H:i:s',time()); $model->mircrotime = microtime(true); if($model->save()===false){ echo '未能成功抢购!'; }else{ echo '恭喜你,订单<b>'.$order.'</b>抢购成功'; } }else{ echo '已被抢购一空!'; } }
將商品庫存設定為20後,透過ab 配置200的並發請求。
ab -n 200 -c 200 http//localhost/highly/normal
執行結果發現庫存變成了負值,商品超賣了。
原因比較簡單,在高並發請求下。在生產訂單,減少庫存之前,會優先查詢到庫存結果。
優化一:修改庫存資料類型
第一種最佳化方法,從資料庫入手。既然查詢到的結果不準確,那我就在庫存減少上做手腳。將庫存的資料型態改成無符號(不能有負值)。
程式碼還是跟上面差不多,只是在庫存減1的地方做了個判斷。避免報錯。
public function actionNormal(){ // 查询库存 $stock = Goods::find()->select('stock')->where(['goods_id'=>100001])->asArray()->one(); // 判断该商品是否还有库存 if ($stock['stock']>0) { // 库存减一 if(Goods::updateAllCounters(['stock' => -1],['goods_id'=>100001])===false){ echo "已被抢购一空!"; return false; } // 生产订单(另外功能,暂且随机赋值) $order = $this->build_order(); // 秒杀信息入库 $model = new Highly(); $model->order_id = $order; $model->goods_name = '秒杀商品'; $model->buy_time = date('Y-m-d H:i:s',time()); $model->mircrotime = microtime(true); if($model->save()===false){ echo '未能成功抢购!'; }else{ echo '恭喜你,订单<b>'.$order.'</b>抢购成功'; } }else{ echo '已被抢购一空!'; } }
這次同樣200的並發,執行結果發現。數據正確,並不會有超賣的情況。
思路其實也比較簡單。因為庫存不能為負值,當庫存等於0時,如果還有值傳進來,則會報錯。請求被終止。
這種最佳化方式,雖然避免了商品超賣的情況。但是另一方面,請求仍然會對資料庫造成壓力。如果多個功能使用此資料庫,會造成效能下降嚴重。
優化二:redis
利用 redis list類型的pop的原子性。在操作資料庫前,做一個驗證。當商品賣完後,就不允許再繼續進行資料庫作業。
// redis list 高并发测试 public function actionRedis(){ $redis = \Yii::$app->redis; // $redis->lpush('mytest',1); $order = $this->build_order(); // echo $order;die; // echo $redis->llen('mytest'); $reg = $redis->lpop('mytest'); if (!$reg) { echo "笨蛋!已经被抢光啦!"; return false; } $redis->close(); $model = new Highly(); $model->order_id = $order; $model->goods_name = '秒杀商品'; $model->buy_time = date('Y-m-d H:i:s',time()); $model->mircrotime = microtime(true); if($model->save()===false){ echo '未能成功抢购!'; }else{ echo '恭喜你,订单<b>'.$order.'</b>抢购成功'; } } // 给redis添加商品 public function actionInsertgoods(){ $count = yii::$app->request->get('count',0); if (empty($count)) { echo '大兄弟,你还没告诉我需要上架多少商品呢!'; return false; } $redis = \Yii::$app->redis; for ($i=0; $i < $count; $i++) { $redis->lpush('mytest',1); } echo '成功添加了'.$redis->llen('mytest').'件商品。'; $redis->close(); }
這點的程式碼,我寫了兩個方法。第一個方法是秒殺的程式碼,第二個方法是為秒殺的商品設定數量。為了方便測試,我這裡處理的比較簡單。
通過測試,資料庫生產的訂單數量正常,並沒有出現問題。而又避免了請求資料庫造成效能下降的問題。同時記憶體資料庫redis查詢的速度比mysql快很多。
相關推薦:
以上是php如何處理搶購類別功能的高並發請求的詳細內容。更多資訊請關注PHP中文網其他相關文章!

PHP和Python各有優勢,選擇應基於項目需求。 1.PHP適合web開發,語法簡單,執行效率高。 2.Python適用於數據科學和機器學習,語法簡潔,庫豐富。

PHP不是在消亡,而是在不斷適應和進化。 1)PHP從1994年起經歷多次版本迭代,適應新技術趨勢。 2)目前廣泛應用於電子商務、內容管理系統等領域。 3)PHP8引入JIT編譯器等功能,提升性能和現代化。 4)使用OPcache和遵循PSR-12標準可優化性能和代碼質量。

PHP的未來將通過適應新技術趨勢和引入創新特性來實現:1)適應云計算、容器化和微服務架構,支持Docker和Kubernetes;2)引入JIT編譯器和枚舉類型,提升性能和數據處理效率;3)持續優化性能和推廣最佳實踐。

在PHP中,trait適用於需要方法復用但不適合使用繼承的情況。 1)trait允許在類中復用方法,避免多重繼承複雜性。 2)使用trait時需注意方法衝突,可通過insteadof和as關鍵字解決。 3)應避免過度使用trait,保持其單一職責,以優化性能和提高代碼可維護性。

依賴注入容器(DIC)是一種管理和提供對象依賴關係的工具,用於PHP項目中。 DIC的主要好處包括:1.解耦,使組件獨立,代碼易維護和測試;2.靈活性,易替換或修改依賴關係;3.可測試性,方便注入mock對象進行單元測試。

SplFixedArray在PHP中是一種固定大小的數組,適用於需要高性能和低內存使用量的場景。 1)它在創建時需指定大小,避免動態調整帶來的開銷。 2)基於C語言數組,直接操作內存,訪問速度快。 3)適合大規模數據處理和內存敏感環境,但需謹慎使用,因其大小固定。

PHP通過$\_FILES變量處理文件上傳,確保安全性的方法包括:1.檢查上傳錯誤,2.驗證文件類型和大小,3.防止文件覆蓋,4.移動文件到永久存儲位置。

JavaScript中處理空值可以使用NullCoalescingOperator(??)和NullCoalescingAssignmentOperator(??=)。 1.??返回第一個非null或非undefined的操作數。 2.??=將變量賦值為右操作數的值,但前提是該變量為null或undefined。這些操作符簡化了代碼邏輯,提高了可讀性和性能。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

WebStorm Mac版
好用的JavaScript開發工具

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

Atom編輯器mac版下載
最受歡迎的的開源編輯器