高并发下用pdo,文件排它锁,redis三种方法对比

时间:2022-01-13 19:23:53
<?phpheader('content-type:text/html;charset=utf-8');              // //无控制    // $DB_DSN = 'mysql:dbname=blog;host=127.0.0.1';    // $DB_USER = 'root';    // $DB_PWD = 'root';         // $pdo = new PDO($DB_DSN, $DB_USER, $DB_PWD);    // $pdo->setAttribute(PDO::ATTR_PERSISTENT, true); // 设置数据库连接为持久连接    // $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 设置抛出错误    // $pdo->setAttribute(PDO::ATTR_ORACLE_NULLS, true); // 设置当字符串为空转换为 SQL 的 NULL    // $pdo->query('SET NAMES utf8'); // 设置数据库编码             // function build_order_no() { //生成唯一订单    //   return date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);    // }         // $price=10;    // $user_id=1;    // $goods_id=1;    // $sku_id=11;    // $number=1;         // //模拟下单操作    // //库存是否大于0    // //解锁 此时ih_store数据中goods_id='$goods_id' and sku_id='$sku_id' 的数据被锁住(注3),其它事务必须等待此次事务 提交后才能执行    // $sql = "select number from ih_store where goods_id='$goods_id' and sku_id='$sku_id'";    // $rs = $pdo->query($sql);    // $row = $rs->FetchColumn();    // if($row > 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 = $pdo->query($sql);              // // var_dump($order_rs);die;    //  //库存减少    //  $sql="update ih_store set number=number-{$number} where sku_id='$sku_id'";    //  $store_rs = $pdo->query($sql);              // //   if($store_rs->rowCount()) {    // //       error_log('订单号:'.$order_sn.'库存减少成功<br>');    // //   } else {    // //       error_log('订单号:'.$order_sn.'库存减少失败<br>');    // //   }     // // }else{    // //   //error_log('库存不够<br>');    // }                        // //开启事物    // $DB_DSN = 'mysql:dbname=blog;host=127.0.0.1';    // $DB_USER = 'root';    // $DB_PWD = 'root';         // $pdo = new PDO($DB_DSN, $DB_USER, $DB_PWD);    // $pdo->setAttribute(PDO::ATTR_PERSISTENT, true); // 设置数据库连接为持久连接    // $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 设置抛出错误    // $pdo->setAttribute(PDO::ATTR_ORACLE_NULLS, true); // 设置当字符串为空转换为 SQL 的 NULL    // $pdo->query('SET NAMES utf8'); // 设置数据库编码             // function build_order_no() { //生成唯一订单    //   return date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);    // }         // $price=10;    // $user_id=1;    // $goods_id=1;    // $sku_id=11;    // $number=1;         // //模拟下单操作    // //库存是否大于0    // //解锁 此时ih_store数据中goods_id='$goods_id' and sku_id='$sku_id' 的数据被锁住(注3),其它事务必须等待此次事务 提交后才能执行     // $pdo->query('BEGIN');     // $sql = "select number from ih_store where goods_id='$goods_id' and sku_id='$sku_id'";    // $rs = $pdo->query($sql);    // $row = $rs->FetchColumn();    // if($row > 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 = $pdo->query($sql);              //  //库存减少    //  $sql="update ih_store set number=number-{$number} where sku_id='$sku_id'";    //  $store_rs = $pdo->query($sql);              //  // if($store_rs->rowCount()) {    //  //  error_log('订单号:'.$order_sn.'库存减少成功<br>');    //      $pdo->query('COMMIT');    //  // } else {    //  //  error_log('订单号:'.$order_sn.'库存减少失败<br>');    //  // }     // // var_dump($order_rs);die;    // }else{    //  //error_log('库存不够<br>');    //  $pdo->query('ROLLBACK');             // }                         // //使用非阻塞的文件排他锁    // $DB_DSN = 'mysql:dbname=blog;host=127.0.0.1';    // $DB_USER = 'root';    // $DB_PWD = 'root';         // $pdo = new PDO($DB_DSN, $DB_USER, $DB_PWD);    // $pdo->setAttribute(PDO::ATTR_PERSISTENT, true); // 设置数据库连接为持久连接    // $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 设置抛出错误    // $pdo->setAttribute(PDO::ATTR_ORACLE_NULLS, true); // 设置当字符串为空转换为 SQL 的 NULL    // $pdo->query('SET NAMES utf8'); // 设置数据库编码             // function build_order_no() { //生成唯一订单    //   return date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);    // }         // $price=10;    // $user_id=1;    // $goods_id=1;    // $sku_id=11;    // $number=1;         // //模拟下单操作    // //库存是否大于0     // $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 = $pdo->query($sql);    // $row = $rs->FetchColumn();         // if($row > 0){ //高并发下会导致超卖     //  $order_sn = build_order_no();                            //  //库存减少    //  $sql="update ih_store set number=number-{$number} where sku_id='$sku_id'";    //  $store_rs = $pdo->query($sql);              //  if($store_rs->rowCount()) {     //          //生成订单     //  $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 = $pdo->query($sql);    //      error_log('订单号:'.$order_sn.'库存减少成功<br>');    //  } else {    //      error_log('订单号:'.$order_sn.'库存减少失败<br>');    //  }    //  flock($fp,LOCK_UN);//释放锁    // }else{    //  error_log('库存不够<br>');    // }    // fclose($fp);                            //队列              $store = 500;    $redis = new Redis();    $result = $redis->connect('127.0.0.1', 6379);    $redis->FLUSHALL();     $res = $redis->llen('goods_store');         $count = $store-$res;    for($i=1;$i<=$count;$i++){        $redis->lpush('goods_store', $i);    }    echo $redis->llen('goods_store');    exit;                           $DB_DSN = 'mysql:dbname=blog;host=127.0.0.1';    $DB_USER = 'root';    $DB_PWD = 'root';         $pdo = new PDO($DB_DSN, $DB_USER, $DB_PWD);    $pdo->setAttribute(PDO::ATTR_PERSISTENT, true); // 设置数据库连接为持久连接    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 设置抛出错误    $pdo->setAttribute(PDO::ATTR_ORACLE_NULLS, true); // 设置当字符串为空转换为 SQL 的 NULL    $pdo->query('SET NAMES utf8'); // 设置数据库编码         function build_order_no() { //生成唯一订单        $sn = microtime().''.rand(10000,100000).''.microtime().''.rand(10000,100000);        return $sn;      //return date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);    }         $price=10;    $user_id=1;    $goods_id=1;    $sku_id=11;    $number=1;         //模拟下单操作    $redis=new Redis();    $result=$redis->connect('127.0.0.1', 6379);    $count = $redis->rpop('goods_store');         if(!$count){        error_log('队列'.$count.'redis:库存不足');    } else {         $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 = $pdo->query($sql);                      //库存减少        $sql="update ih_store set number=number-{$number} where sku_id='$sku_id'";        $store_rs = $pdo->query($sql);                  if($store_rs->rowCount()) {            error_log('队列:'.$count.'订单号:'.$order_sn.'库存减少成功<br>');        } else {            error_log('队列:'.$count.'订单号:'.$order_sn.'库存减少失败<br>');        }    }    



自我感觉,文件排它锁比较慢,pdo处理高并发效果一般,redis是最有效的