PHP处理库存超卖的几种处理方法
第一种方法:使用mysql数据库的锁机制。在事务中使用 for update 语句,在事务处理完成之后释放这一条数据。
代码使用tp5的框架:
public function mysqlLock(){ $goods_id = 26545; $sku_id = 26545; $price = 300; $user = ''; StoreOrderModel::startTrans(); $nums = StoreOrderModel::where(['id'=>1])->field('number')->lock(true)->find(); $nums = $nums['number']; if($nums > 0){ $item['goods_id'] = $goods_id; $item['sku_id'] = $sku_id; $item['number'] = $nums; $item['price'] = $price; $item['user'] = $user; $id = StoreModel::insertGetId($item); if($id){ StoreOrderModel::where(['id'=>1])->setDec('number'); StoreOrderModel::commit(); }else{ StoreOrderModel::rollback(); } }else{ echo "没有库存了"; } }
第二种方法:redis 事务。
public function start_reids_tran(){ $goods_id = 26545; $sku_id = 26545; //$number = 1; $price = 300; $user = ''; $redis = ResRedisModel::getinstance(); $redis->watch('store'); $nums = intval($redis->get('store')); if($nums > 0){ $item['goods_id'] = $goods_id; $item['sku_id'] = $sku_id; $item['number'] = $nums; $item['price'] = $price; $item['user'] = $user; $redis->lPush('success', json_encode($item)); $redis->multi(); $redis->decr('store'); $replies = $redis->exec(); // 执行以上 redis 事务 if(!$replies){ echo "订单 {$nums} 回滚".PHP_EOL; } $redis->unwatch(); echo "抢购成功!".PHP_EOL; }else{ echo "没有库存了"; } }
第三种方法:redis 队列,预先把库存信息存入队列当中,抢购时判断队列的数量,然后出队。队列为空时库存为0。
public function eq_start(){ $redis = ResRedisModel::getinstance(); $nums = $redis->lSize('store'); $goods_id = 26545; $sku_id = 26545; $number = 1; $price = 300; $user = ''; if($nums > 0){ $user = $redis->rPop('store'); if($user){ $item['goods_id'] = $goods_id; $item['sku_id'] = $sku_id; $item['number'] = $number; $item['price'] = $price; $item['user'] = $user; StoreModel::insertGetId($item); echo '抢购成功!'; }else{ echo '抢购失败!'; } }else{ echo '抢购失败!'; } }
第四种:文件排他锁方式
public function file_star(){ $fp = fopen('D:/phpStudy/PHPTutorial/www/public/lock.txt', "r"); if(flock($fp, LOCK_EX)) { //排他型锁定 阻塞模式 , flock($fp,LOCK_EX | LOCK_NB) 非阻塞模式 $nums = StoreOrderModel::where(['id'=>1])->field('number')->find(); $nums = $nums['number']; if($nums > 0){ $goods_id = 26545; $sku_id = 26545; $number = 1; $price = 300; $user = '213'; $item['goods_id'] = $goods_id; $item['sku_id'] = $sku_id; $item['number'] = $number; $item['price'] = $price; $item['user'] = $user; StoreModel::insertGetId($item); StoreOrderModel::where(['id'=>1])->setDec('number'); flock($fp, LOCK_UN); //释放锁定 echo '抢购成功!'; }else{ echo '没有库存了!'; } }else{ echo '抢购失败!'; } fclose($fp); }