当前位置:首页 > PHP

商品秒杀实现php

2026-02-28 00:04:29PHP

商品秒杀系统的核心设计

高并发场景下,商品秒杀系统需要解决超卖、性能瓶颈和公平性问题。PHP实现需结合数据库优化、缓存和队列技术。

数据库设计

创建秒杀商品表和订单表,关键字段需添加索引:

CREATE TABLE `seckill_goods` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `stock` int(11) NOT NULL,
  `start_time` datetime NOT NULL,
  `end_time` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_time` (`start_time`,`end_time`)
);

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 `uk_user_goods` (`user_id`,`goods_id`)
);

库存预加载

活动开始前将库存加载到Redis:

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$goodsId = 1;
$stock = 1000; // 从数据库获取实际库存
$redis->set("seckill:goods:$goodsId:stock", $stock);

原子性扣减库存

使用Redis Lua脚本保证原子操作:

$lua = <<<LUA
local stock = tonumber(redis.call('GET', KEYS[1]))
if stock <= 0 then
    return 0
end
redis.call('DECR', KEYS[1])
return 1
LUA;

$goodsKey = "seckill:goods:$goodsId:stock";
$result = $redis->eval($lua, [$goodsKey], 1);

消息队列处理订单

库存扣减成功后投递订单到RabbitMQ:

$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();
$channel->queue_declare('order_queue', false, true, false, false);

$orderData = json_encode([
    'user_id' => $userId,
    'goods_id' => $goodsId
]);

$msg = new AMQPMessage($orderData, ['delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT]);
$channel->basic_publish($msg, '', 'order_queue');

防重复购买

使用Redis SET记录已购买用户:

$userKey = "seckill:goods:$goodsId:users";
if ($redis->sAdd($userKey, $userId)) {
    // 允许购买
} else {
    // 已购买过
}

接口限流

使用Redis实现令牌桶限流:

$rateLimitKey = "seckill:rate_limit:$goodsId";
$capacity = 1000; // 最大请求数
$rate = 100; // 每秒恢复数量

$now = microtime(true);
$lastTime = $redis->get("$rateLimitKey:last_time") ?: $now;
$tokens = $redis->get("$rateLimitKey:tokens") ?: $capacity;

$elapsed = $now - $lastTime;
$tokens = min($capacity, $tokens + $elapsed * $rate);

if ($tokens < 1) {
    http_response_code(429);
    exit;
}

$tokens--;
$redis->set("$rateLimitKey:last_time", $now);
$redis->set("$rateLimitKey:tokens", $tokens);

数据库最终一致性

消费队列处理实际订单:

$callback = function ($msg) {
    $orderData = json_decode($msg->body, true);

    try {
        $pdo = new PDO('mysql:host=localhost;dbname=seckill', 'root', '');
        $pdo->beginTransaction();

        $stmt = $pdo->prepare("INSERT INTO seckill_orders VALUES (NULL, ?, ?, NOW())");
        $stmt->execute([$orderData['user_id'], $orderData['goods_id']]);

        $stmt = $pdo->prepare("UPDATE seckill_goods SET stock = stock - 1 WHERE id = ?");
        $stmt->execute([$orderData['goods_id']]);

        $pdo->commit();
        $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
    } catch (Exception $e) {
        $pdo->rollBack();
        // 记录失败或重试
    }
};

$channel->basic_consume('order_queue', '', false, false, false, false, $callback);

系统优化建议

采用Nginx负载均衡分流请求,PHP建议使用Swoole扩展提升并发处理能力。静态资源部署到CDN,活动页面做静态化处理。数据库主从分离,读写操作分配到不同实例。

商品秒杀实现php

标签: 商品秒杀
分享给朋友:

相关文章

php 实现秒杀

php 实现秒杀

PHP 实现秒杀的关键技术 秒杀系统需要解决高并发、超卖、性能瓶颈等问题。以下是实现秒杀的核心方案: 使用 Redis 预减库存 将商品库存提前加载到 Redis 中,通过原子操作保证库存准确性:…

php实现秒杀

php实现秒杀

PHP实现秒杀功能的关键技术 秒杀系统需要解决高并发、数据一致性、系统稳定性等问题。以下是PHP实现秒杀功能的核心技术方案: 数据库优化 使用InnoDB引擎的行级锁和事务特性,确保数据一致性。商…

vue 实现商品页面

vue 实现商品页面

实现商品页面的基本步骤 使用Vue.js实现商品页面需要结合组件化开发、数据绑定和路由等功能。以下是一个典型实现方案: 商品数据管理 商品数据通常存储在Vuex或Pinia状态管理中,也可以通过AP…

vue实现商品卡片

vue实现商品卡片

Vue 实现商品卡片 在 Vue 中实现商品卡片可以通过组件化的方式完成,以下是一个完整的实现方案: 商品卡片组件 <template> <div class="product…

vue实现商品橱窗

vue实现商品橱窗

实现商品橱窗的基本结构 使用Vue.js创建商品橱窗需要先搭建基本结构。商品橱窗通常包含商品列表、商品卡片、筛选和排序功能。在Vue项目中,可以通过组件化方式实现这些功能。 创建商品列表组件,用于展…

vue实现添加商品功能

vue实现添加商品功能

数据绑定与表单结构 在Vue中实现添加商品功能,通常需要使用v-model进行表单数据双向绑定。创建一个包含商品名称、价格、库存等字段的表单结构,通过data()初始化商品对象: <temp…