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);
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值