php抢购功能实现
PHP抢购功能实现
抢购功能需要处理高并发、数据一致性和系统稳定性等问题。以下是实现抢购功能的关键步骤和技术要点。
数据库设计
创建商品表和订单表,确保商品库存字段使用无符号整数类型,便于数据库层面防止超卖。
CREATE TABLE `goods` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL DEFAULT '',
`stock` int(11) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `orders` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`goods_id` int(11) unsigned NOT NULL,
`user_id` int(11) unsigned NOT NULL,
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
悲观锁实现
使用数据库悲观锁确保数据一致性,在事务中锁定商品记录。

$pdo->beginTransaction();
try {
$stmt = $pdo->prepare("SELECT stock FROM goods WHERE id = ? FOR UPDATE");
$stmt->execute([$goodsId]);
$stock = $stmt->fetchColumn();
if ($stock > 0) {
$pdo->prepare("UPDATE goods SET stock = stock - 1 WHERE id = ?")->execute([$goodsId]);
$pdo->prepare("INSERT INTO orders (goods_id, user_id) VALUES (?, ?)")->execute([$goodsId, $userId]);
$pdo->commit();
echo "抢购成功";
} else {
$pdo->rollBack();
echo "库存不足";
}
} catch (Exception $e) {
$pdo->rollBack();
echo "系统繁忙";
}
乐观锁实现
使用版本号或CAS机制实现乐观锁,减少锁竞争。
UPDATE goods
SET stock = stock - 1, version = version + 1
WHERE id = ? AND stock > 0 AND version = ?
Redis队列实现
使用Redis的原子操作特性,将抢购请求放入队列处理。

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$key = "seckill:goods:$goodsId";
if ($redis->decr($key) >= 0) {
// 异步处理订单
$redis->lPush("seckill:queue", json_encode(['goods_id' => $goodsId, 'user_id' => $userId]));
echo "抢购成功";
} else {
$redis->incr($key); // 恢复库存
echo "库存不足";
}
限流措施
使用Redis实现计数器限流,防止系统过载。
$limitKey = "seckill:limit:$userId";
if ($redis->incr($limitKey) > 1) {
$redis->expire($limitKey, 60);
die("操作过于频繁");
}
静态化处理
对商品详情页进行静态化处理,减轻服务器压力。
ob_start();
// 渲染商品页面
$content = ob_get_clean();
file_put_contents("/static/goods_{$goodsId}.html", $content);
服务降级
准备降级方案,当系统压力过大时关闭非核心功能。
if ($systemOverload) {
header("HTTP/1.1 503 Service Unavailable");
echo "系统繁忙,请稍后再试";
exit;
}
注意事项
- 前端需要增加倒计时和按钮防重复点击
- 后端日志需要详细记录抢购过程
- 压力测试必不可少
- 分布式环境下需要分布式锁
- 考虑使用消息队列异步处理订单
通过以上方法组合使用,可以构建一个相对稳定的抢购系统。实际项目中需要根据具体业务需求进行调整和优化。






