1、超發原因
假設某個搶購場景中,我們總共只有100個商品,在最後一刻,我們已經消耗了99個商品,只剩下最後一個。這時候,系統發來多個並發請求,這批請求讀取到的商品餘裕都是99個,然後都通過了這一個餘量判斷,最終導致超發。
在上面的這個圖中,就導致了並髮用戶B也“搶購成功”,多讓一個人獲得了商品。這種場景,在高並發的情況下非常容易出現。
檔案鎖定思路
對於日IP不高或說並發數不是很大的應用,一般不用考慮這些!用一般的文件操作方法完全沒有問題。但如果並發高,在我們對文件進行讀寫操作時,很有可能多個進程對進一文件進行操作,如果這時不對文件的存取進行相應的獨佔,就容易造成數據丟失。
最佳化方案:使用非阻塞的檔案排他鎖定
<?php //优化方案4:使用非阻塞的文件排他锁 include ('./mysql.php'); //生成唯一订单号 function build_order_no(){ return date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8); } //记录日志 function insertLog($event,$type=0){ global $conn; $sql="insert into ih_log(event,type) values('$event','$type')"; mysqli_query($conn,$sql); } $fp = fopen("lock.txt", "w+"); if(!flock($fp,LOCK_EX | LOCK_NB)){ echo "系统繁忙,请稍后再试"; return; } //下单 $sql="select number from ih_store where goods_id='$goods_id' and sku_id='$sku_id'"; $rs = mysqli_query($conn,$sql); $row = $rs->fetch_assoc(); if($row['number']>0){//库存是否大于0 //模拟下单操作 $order_sn=build_order_no(); $sql="insert into ih_order(order_sn,user_id,goods_id,sku_id,price) values('$order_sn','$user_id','$goods_id','$sku_id','$price')"; $order_rs = mysqli_query($conn,$sql); //库存减少 $sql="update ih_store set number=number-{$number} where sku_id='$sku_id'"; $store_rs = mysqli_query($conn,$sql); if($store_rs){ echo '库存减少成功'; insertLog('库存减少成功'); flock($fp,LOCK_UN);//释放锁 }else{ echo '库存减少失败'; insertLog('库存减少失败'); } }else{ echo '库存不够'; insertLog('库存不够'); } fclose($fp); ?>
推薦教學:PHP影片教學
以上是php如何防止高併發的詳細內容。更多資訊請關注PHP中文網其他相關文章!