本文提供 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();
?>
2:(使用文件鎖),代碼如下:
<?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 "秒殺失敗";
}
?>
