This article provides a PHP high concurrency spike solution (add three case descriptions (normal process, use file lock, use redis message queue))
1: (normal process, do not do any high concurrency processing), the code is as follows:
<?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: (using file lock), the code is as follows:
<?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 "The system is busy, please try again later"; return; } if($_assoc['stock']>0){ $_sql = "UPDATE goods SET stock=stock-1 WHERE id=2"; if($_mysqli->query($_sql)){ flock($fp,LOCK_UN);//Release the lock } } fclose($fp); $_mysqli->close(); ?>
3: Use redis message queue, the code is as follows:
<?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); //Before the seckill starts, first store the inventory quantity in the queue, cooperate with scheduled tasks, and tentatively set the inventory to 100 } echo $redis->llen('goods_nums'); exit(); */ $check = $redis->lpop('goods_nums'); //echo $check; if($check){ echo "Seckill success"; $_sql = "UPDATE goods SET stock=stock-1 WHERE id=3"; $_mysqli->query($_sql); return; } else { echo "Seckill failed"; } ?>