PHP 高并发秒杀解决方案(有demo)

 
本文提供 PHP 高并发秒杀解决方案(附加三个案例说明(普通流程,使用文件锁,使用redis消息队列)):
 
1:(正常流程,不做任何高并发处理),代码如下:
 
<?php

$_mysqli = new mysqli('localhost','root','','secondkill');

if (mysqli_connect_errno()) {
echo mysqli_connect_error();
exit();
}
$_mysqli->set_charset('utf8');

$_sql = "select stock from goods where id=1";

$_result = $_mysqli->query($_sql);

$_assoc = $_result->fetch_assoc();

if($_assoc['stock']>0){
$_sql = "UPDATE goods SET stock=stock-1 WHERE id=1";
$_mysqli->query($_sql);

}

$_mysqli->close();

?>

1:(使用文件锁),代码如下:
 
<?php


$_mysqli = new mysqli('localhost','root','','secondkill');

if (mysqli_connect_errno()) {
echo mysqli_connect_error();
exit();
}
$_mysqli->set_charset('utf8');

$_sql = "select stock from goods where id=2";

$_result = $_mysqli->query($_sql);

$_assoc = $_result->fetch_assoc();

$fp = fopen("lock.txt", "w+");
if(!flock($fp,LOCK_EX | LOCK_NB)){
echo "系统繁忙,请稍后再试";
return;
}

if($_assoc['stock']>0){
$_sql = "UPDATE goods SET stock=stock-1 WHERE id=2";
if($_mysqli->query($_sql)){
flock($fp,LOCK_UN);//释放锁
}

}

fclose($fp);
$_mysqli->close();



?>

3:使用redis 消息队列,代码如下:
 
<?php

$redis=new Redis();
$result=$redis->connect('127.0.0.1',6379);

$_mysqli = new mysqli('localhost','root','','secondkill');

if (mysqli_connect_errno()) {
echo mysqli_connect_error();
exit();
}
$_mysqli->set_charset('utf8');

/*
for($i=1;$i<=100;$i++){
$redis->lpush('goods_nums',$i); //秒杀开始前,先将库存数量存在队列,配合定时任务,暂定库存为100
}

echo $redis->llen('goods_nums');
exit();
*/

$check = $redis->lpop('goods_nums');

//echo $check;

if($check){
echo "秒杀成功";
$_sql = "UPDATE goods SET stock=stock-1 WHERE id=3";
$_mysqli->query($_sql);
return;
} else {
echo "秒杀失败";
}


?>

测试办法:(使用apache ab 测试工具模拟并发):
 
./ab -n 6000 -c 5000 http://localhost/index.php //普通

./ab -n 6000 -c 5000 http://localhost/file.php //文件锁

./ab -n 6000 -c 5000 http://localhost/redis.php //redis消息队列

反复测试,得出结果如下:
 
id     stock

1    -2
2    0
3    0

 
 
PS:
id 1   普通流程
id 2  使用文件锁
id 3  使用redis消息队列
最后附上表结构 sql:
 
 

1 个评论

赞!厉害!

要回复文章请先登录注册