In the previous article "How to prevent product inventory oversold under high concurrency in PHP", we talked about related issues about preventing oversold product inventory under high concurrency. Let's do it together. Let’s take a look at the related content of concurrency testing to prevent inventory oversold. I hope it will be helpful to everyone.
This article is based on the test case of "How to prevent product inventory from being oversold under high concurrency in PHP". Recommended study: "PHP Learning Tutorial"
During concurrent testing, product table id =1 name = Daohuaxiang Rice store = 15
请求总数30 每次10个并发 ab -n 30 -c 10 http://xxxxx.top/code/the_limit/add_order.php
Result:
There were 15 successful inventory reductions, and the store inventory had a negative number of -7. 8 times it was judged that the inventory was insufficient (negative inventory numbers are incorrect and not allowed)
Adjust back to product table id =1 name = Daohuaxiang Rice store = 15
请求总数30 每次10个并发 ab -n 30 -c 10 http://xxxxx.top/code/the_limit/unsigned.php
Result:
There have been 15 successful inventory reductions and the store inventory has a negative number of -6. 9 times it was judged that the inventory was insufficient (negative inventory numbers are incorrect and not allowed)
Only adding for update to the query statement has little effect in locking
Adjust back to product table id =1 name = Daohuaxiang Rice store = 15
请求总数30 每次10个并发 ab -n 30 -c 10 http://xxxxx.top/code/the_limit/ACID.php
Result:
There were 15 successful inventory reductions. The store did not have a negative inventory. 15 times it was judged that the inventory was insufficient (negative inventory numbers are incorrect and not allowed)
The effect of adding transactions is good ab -n 3000 -c 1000 concurrency can also be tolerated
Blocking form
Non-blocking Form
The effect does not appear negative, but in terms of performance: Transaction>Blocking>Non-blocking
The code is slightly different from the previous one There are adjustments to the optimistic lock version
<?php $redis =new Redis(); $redis->connect("127.0.0.1", 6379); $redis->auth('PASSWORD'); $redis->watch('sales');//乐观锁 监视作用 set() 初始值0 $sales = $redis->get('sales'); //var_dump($sales); exit; db(); global $con; // 查询商品信息 //$product_id = 1; //$sql = "select * from products where id={$product_id}"; //$result = mysqli_query($con, $sql); //$row = mysqli_fetch_assoc($result); //$store = $row['store']; // 库存 $n = 15; if ($sales >= $n) { insertLog('库存为0 秒杀失败'); exit('秒杀结束'); } //redis开启事务 $redis->multi(); $redis->incr('sales'); //将 key 中储存的数字值增一 ,如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。 $res = $redis->exec(); //成功1 失败0 if ($res) { //秒杀成功 $con = new mysqli('localhost','root','PASSWORD','dev'); if (!$con) { echo "数据库连接失败"; } $product_id = 1;// 商品ID $buy_num = 1;// 购买数量 sleep(1); $sql = "update products set store=store-{$buy_num} where id={$product_id}"; if (mysqli_query($con, $sql)) { echo "秒杀完成"; insertLog('恭喜 秒杀成功'); } } else { insertLog('抱歉 秒杀失败'); exit('抢购失败'); } function db() { global $con; $con = new mysqli('localhost','root','WOrd1234.*','dev'); if (!$con) { echo "数据库连接失败"; } } /** * 记录日志 */ function insertLog($content) { global $con; $sql = "INSERT INTO `order_log` (content) values('$content')"; mysqli_query($con, $sql); }
ab -n 30 -c 10 http://xxxxxx.top/code/the_limit/optimistic\ _redis_lock.php
Final conclusion Concurrency challenges give priority to redis with good performance
Recommended learning: "PHP Video Tutorial"
The above is the detailed content of PHP high concurrency testing: Case study on preventing inventory oversold. For more information, please follow other related articles on the PHP Chinese website!