标签:reac 比较 HERE 9.png ror html 测试的 round 了解
处理库存超卖的情况前,先了解下什么是乐观锁和悲观锁,下面的几篇博客已经介绍的比较详细了,我就不在赘述其原理了
下面开始介绍悲观锁在实际中的应用了
//下订单
..........
try {
M()->startTrans();
//判断商品是否有赠品 $give_gift=$ob->getGiveGoods($sku_nos); if(!empty($give_gift)){ $this->dealSkuGift($give_gift,$ob,$data[‘order_no‘],$skuNumArr,$packageSku); }
}catch(FlException $ex) {
M()->rollback();
$curCode = $ex->getErrorCode();
$curmsg = $ex->getMessage();
E($curCode, $curmsg);
}
M()->commit();
..........
//获取赠品库存
public function getGiveGoodsStock($sku_no){ $sku_no=implode(",",array_unique($sku_no)); $sku_no = "‘".str_replace(",","‘,‘",$sku_no)."‘"; $Model = new \Think\Model(); $sku_gift_info=$Model->query("select sku_no,stock from ".C(‘DB_PREFIX‘)."sku_gift_stock where is_deleted=0 and is_online=1 and sku_no in($sku_no) for update"); return $sku_gift_info; }
// 处理赠品
private function dealSkuGift($give_gift,$ob,$orderNo,$skuNumArr,$packageSku){ if(empty($give_gift) or empty($skuNumArr)){ return false; } $skuGiftStockM=M(‘sku_gift_stock‘); $sku_gifts=array_column($give_gift,‘sku_no‘); //获取赠品库存 $sku_give_gift=$ob->getGiveGoodsStock($sku_gifts,1); $skuGiftStock=array(); $giftCount=0; foreach($sku_give_gift as $k=>$v){ $skuGiftStock[$v[‘sku_no‘]]=$v[‘stock‘]; } $public = new PModel(); foreach ($give_gift as $v){ $goodsNums=0; $delStockWhere=array(); if($v[‘isHaveStock‘]==‘1‘ && $skuGiftStock[$v[‘sku_no‘]] >0){//代表有货--这些是需要发货的 if($v[‘type‘]==‘1‘){ $lastGiftNum=$skuNumArr[$v[‘parent_sku_no‘]]*$v[‘goods_nums‘]; }else{//按固定赠品数量 $lastGiftNum=$v[‘goods_nums‘]; } if($lastGiftNum >= $v[‘stock_num‘]){ $lastGiftNum=$v[‘stock_num‘]; } if($v[‘stock_num‘]==0){ $lastGiftNum=0; } $delStockWhere[‘sku_no‘]=$v[‘sku_no‘]; $delStockWhere[‘is_deleted‘]=0; $delStockWhere[‘is_online‘]=1; $delStockWhere[‘_string‘]= sprintf(‘stock>=%d‘, $lastGiftNum); $skuGiftStockM->where($delStockWhere)->lock(true)->setDec(‘stock‘,$lastGiftNum);//扣除商品赠品库存 $re_v=$public->updataSignData($v[‘sku_no‘],$lastGiftNum,‘virtual_inventory‘,‘-‘,‘goods_sku‘,‘sku_no‘);//扣除赠品商品库存 if(false == $re_v){ E(‘300110‘); } $giftCount+=$lastGiftNum; }else{ $lastGiftNum=0; } $dd[]=array( ‘parent_sku_no‘=>$v[‘parent_sku_no‘], ‘sku_no‘=>$v[‘sku_no‘], ‘num‘=>$lastGiftNum,//最终发货的数量,无货为0 ‘create_time‘=>date(‘Y-m-d H:i:s‘,time()), ‘order_no‘=>$orderNo, ‘package_id‘=>$packageSku[$v[‘parent_sku_no‘]], ‘stock_num‘=>empty($skuGiftStock[$v[‘sku_no‘]])?0:$skuGiftStock[$v[‘sku_no‘]] ); } $order_goods_gift=M(‘order_goods_gift‘); $order_goods_gift->addAll($dd); $upOrdeData=array( ‘gift_count‘=>$giftCount+1 ); M(‘order‘)->where(‘order_no="‘.$orderNo.‘"‘)->data($upOrdeData)->save(); return true;
}
//接口访问方式
//由于要测试并发下该接口的超卖处理情况,所以访问接口前,可将body里的参数写死到接口内,这样方便调试
//再次访问接口
//下面就可以用apache的ab工具对下单接口进行并发测试了
到数据库里查看商品P002026-01关联了2个赠品,各关联了10个
查看赠品的库存数量
apache并发测试的原理及使用方法参见博客:https://www.cnblogs.com/lishuyi/p/5808661.html
使用方法:
ab -n 10 -c 5 http://app.zouke.com/ (-n发出10个请求,-c模拟5个并发,相当5人同时访问,后面是测试url) ab -t 60 -c 100 http://192.168.0.10/ 在60秒内发请求,一次100个请求。
先预测下,请求10次,并发5个,最终的库存会剩余0
下面开始并发测试
最终赠品P002872、P002962的剩余库存如下
结果可见,本次悲观锁起了效果,下面看下不用悲观锁的情况会是什么样,下面将2个赠品的库存都恢复为10个,并将获取赠品库存代码进行改造,这次获取赠品库存是没加悲观锁的
//获取赠品库存 public function getGiveGoodsStock($sku_no,$ori){ $sku_gift=M(‘sku_gift_stock‘); $sgg_where[‘sku_no‘]=array(‘in‘,$sku_no); $sgg_where[‘is_deleted‘]=0; $sgg_where[‘is_online‘]=1; $sku_gift_info=$sku_gift->field(‘sku_no,stock‘)->where($sgg_where)->select(); return $sku_gift_info; }
再次并发测试一下
发现赠品库存是变为负数了,这是超卖的情况出现了
好了,以上测试可以了,下面看下直接用操作数据表看下效果,按如下顺序执行,发现当执行完前4步后,用户B查询不到赠品库存信息,主要是因为此时赠品表已经锁住了
下面执行用户A第5步COMMIT,用户B查询赠品库存立马查询出来了
上述可见,mysql悲观锁对赠品库存超卖的处理流程的生效过程了
标签:reac 比较 HERE 9.png ror html 测试的 round 了解
原文地址:https://www.cnblogs.com/zouke1220/p/9096077.html