Preventing Overselling in High‑Concurrency PHP E‑commerce: Test Cases and Solutions
This article evaluates several PHP approaches—including plain inserts, unsigned mode, MySQL transactions, file locks, and Redis queues—to prevent product inventory overselling under high concurrency, presenting test setups, results, and a final recommendation favoring Redis for its superior performance.
The article investigates how to avoid product inventory overselling in a PHP e‑commerce system when handling high concurrency, using a product with initial stock of 15 and 30 total requests (10 concurrent per batch) as the test scenario.
Test 1 – Plain Order : Executed with ab -n 30 -c 10 http://xxxxx.top/code/the_limit/add_order.php. Result: 15 successful stock deductions, inventory dropped to -7, and 8 requests correctly reported insufficient stock, indicating the plain method allows negative inventory.
Test 2 – Unsigned Mode : Executed with ab -n 30 -c 10 http://xxxxx.top/code/the_limit/unsigned.php. Result: 15 successful deductions, inventory reached -6, and 9 insufficient‑stock detections; adding FOR UPDATE lock on the query had little effect.
Test 3 – MySQL Transaction (Row Lock) : Executed with ab -n 30 -c 10 http://xxxxx.top/code/the_limit/ACID.php. Result: 15 successful deductions, inventory never became negative, and 15 correctly reported insufficient stock; the transaction handled 3000 requests with 1000 concurrent threads without failure.
Test 4 – Non‑Blocking File Exclusive Lock : Compared blocking and non‑blocking file locks; both prevented negative inventory, but performance ranked as Transaction > Blocking Lock > Non‑Blocking Lock.
Test 5 – Redis Queue with Optimistic Lock (code excerpt):
<?php
$redis = new Redis();
$redis->connect("127.0.0.1", 6379);
$redis->auth('PASSWORD');
$redis->watch('sales'); // optimistic lock
$sales = $redis->get('sales');
$n = 15;
if ($sales >= $n) {
insertLog('库存为0 秒杀失败');
exit('秒杀结束');
}
$redis->multi();
$redis->incr('sales');
$res = $redis->exec(); // 1 on success, 0 on failure
if ($res) {
// proceed with MySQL update
$con = new mysqli('localhost','root','PASSWORD','dev');
$product_id = 1;
$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);
}
?>The corresponding load test command was
ab -n 30 -c 10 http://xxxxxx.top/code/the_limit/optimistic_redis_lock.php. This approach kept inventory from going negative and demonstrated the best performance among all methods.
Final Conclusion : For high‑concurrency flash‑sale scenarios, using Redis with an optimistic lock provides the most reliable and fastest solution to prevent overselling.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
php Courses
php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
