php秒杀功能的实现
秒杀功能的核心设计
高并发场景下秒杀系统的核心在于解决超卖问题和性能瓶颈。需要结合缓存、队列、锁机制等技术实现。
数据库设计
商品表需包含库存字段,例如:
CREATE TABLE `seckill_goods` (
`id` int(11) NOT NULL,
`name` varchar(100) NOT NULL,
`stock` int(11) NOT NULL COMMENT '库存',
`start_time` datetime NOT NULL COMMENT '秒杀开始时间',
`end_time` datetime NOT NULL COMMENT '秒杀结束时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
订单表记录秒杀成功记录:
CREATE TABLE `seckill_orders` (
`id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`goods_id` int(11) NOT NULL,
`create_time` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
乐观锁实现
通过版本号控制并发:
// 获取商品信息时同时获取版本号
$goods = $db->query("SELECT stock, version FROM seckill_goods WHERE id = $goods_id");
// 更新时校验版本号
$result = $db->execute(
"UPDATE seckill_goods SET stock = stock - 1, version = version + 1
WHERE id = $goods_id AND version = {$goods['version']}"
);
if ($db->affectedRows() > 0) {
// 创建订单
$db->execute("INSERT INTO seckill_orders (...) VALUES (...)");
}
Redis预减库存
活动开始前将库存加载到Redis:
$redis = new Redis();
$redis->set("seckill:goods:$goods_id:stock", 1000);
秒杀时原子操作递减:
$remaining = $redis->decr("seckill:goods:$goods_id:stock");
if ($remaining >= 0) {
// 进入下单队列
$redis->lPush("seckill:order_queue", json_encode([
'user_id' => $userId,
'goods_id' => $goodsId
]));
} else {
// 已售罄
}
消息队列处理
使用RabbitMQ处理实际下单:
// 生产者
$channel->queue_declare('order_queue');
$msg = new AMQPMessage($orderData);
$channel->basic_publish($msg, '', 'order_queue');
// 消费者
$callback = function ($msg) {
// 处理订单创建
createOrder(json_decode($msg->body, true));
$msg->ack();
};
$channel->basic_consume('order_queue', '', false, false, false, false, $callback);
限流措施
使用Redis实现计数器限流:
$key = "seckill:user:$userId:request";
$count = $redis->incr($key);
$redis->expire($key, 10);
if ($count > 5) {
// 超过限制次数
return false;
}
系统优化建议
前端实施按钮防重复点击
document.getElementById('seckill-btn').addEventListener('click', function() {
this.disabled = true;
// 提交请求
});
Nginx层限流配置:
limit_req_zone $binary_remote_addr zone=seckill:10m rate=10r/s;
location /seckill {
limit_req zone=seckill burst=20;
proxy_pass http://backend;
}
注意事项
活动开始前预热Redis数据 库存回补机制需要单独设计 分布式环境下需使用RedLock等分布式锁 监控系统需实时监控库存和订单量







