高并发下用pdo,文件排它锁,redis三种方法对比
<?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是最有效的

浙公网安备 33010602011771号