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 중국어 웹사이트의 기타 관련 기사를 참조하세요!