php实现商品秒杀
PHP实现商品秒杀的核心逻辑
商品秒杀系统需要解决高并发、库存超卖、系统稳定性等问题。以下是关键实现步骤和优化方案。
数据库设计
创建商品表和秒杀活动表,确保字段设计合理:
CREATE TABLE `seckill_goods` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`stock` int(11) NOT NULL COMMENT '库存',
`start_time` datetime NOT NULL COMMENT '开始时间',
`end_time` datetime NOT NULL COMMENT '结束时间',
PRIMARY KEY (`id`)
);
CREATE TABLE `seckill_orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`goods_id` int(11) NOT NULL,
`create_time` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uid_gid` (`user_id`,`goods_id`) COMMENT '防止重复购买'
);
使用Redis预减库存
在秒杀开始前将库存加载到Redis,避免频繁访问数据库:
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->set('seckill_goods_1_stock', 100); // 初始化库存
内存队列削峰
使用Redis列表作为队列缓冲请求:

// 用户请求入队
$redis->lPush('seckill_queue', json_encode([
'user_id' => $userId,
'goods_id' => $goodsId
]));
悲观锁保证原子性
MySQL事务配合行锁确保库存扣减安全:
$pdo->beginTransaction();
try {
$stmt = $pdo->prepare("SELECT stock FROM seckill_goods WHERE id = ? FOR UPDATE");
$stmt->execute([$goodsId]);
$stock = $stmt->fetchColumn();
if ($stock > 0) {
$pdo->prepare("UPDATE seckill_goods SET stock = stock - 1 WHERE id = ?")->execute([$goodsId]);
$pdo->prepare("INSERT INTO seckill_orders (...) VALUES (...)")->execute([...]);
$pdo->commit();
} else {
$pdo->rollBack();
}
} catch (Exception $e) {
$pdo->rollBack();
}
乐观锁实现
通过版本号控制并发:

UPDATE seckill_goods
SET stock = stock - 1, version = version + 1
WHERE id = ? AND version = ? AND stock > 0
接口限流措施
使用Redis计数器限制单位时间请求量:
$key = 'seckill_' . $goodsId . '_' . floor(time()/10);
if ($redis->incr($key) > 1000) {
die('请求过于频繁');
}
服务分离架构
将秒杀系统与主业务分离:
- 独立域名部署
- 单独数据库实例
- 静态资源CDN加速
- 排队系统分流
前端优化策略
- 按钮倒计时控制
- 提交后禁用按钮
- 验证码防机器人
- 本地时间校准
压力测试要点
使用ab或JMeter模拟测试:
- 逐步增加并发量
- 监控系统资源消耗
- 验证库存准确性
- 测试熔断机制
以上方案需要根据实际业务场景调整参数,分布式环境下还需考虑Redis集群、数据库分库分表等扩展方案。






