当前位置:首页 > PHP

php秒杀 实现过程

2026-02-27 10:48:58PHP

数据库设计

创建商品表和订单表,商品表需包含库存字段(stock),订单表记录秒杀成功的用户信息。使用事务和锁机制确保数据一致性。

CREATE TABLE `seckill_goods` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `stock` int(11) NOT NULL,
  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` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
);

悲观锁实现

在事务中使用SELECT...FOR UPDATE锁定商品记录,防止其他请求同时修改库存。检查库存充足后执行减库存和创建订单操作。

$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 (user_id, goods_id) VALUES (?, ?)")->execute([$userId, $goodsId]);
    }
    $pdo->commit();
} catch (Exception $e) {
    $pdo->rollBack();
    throw $e;
}

乐观锁实现

通过版本号或条件更新实现,在UPDATE语句中增加库存判断条件,利用affectedRows判断是否秒杀成功。

$pdo->beginTransaction();
try {
    $affected = $pdo->prepare("UPDATE seckill_goods SET stock = stock - 1 WHERE id = ? AND stock > 0")
              ->execute([$goodsId]);

    if ($affected > 0) {
        $pdo->prepare("INSERT INTO seckill_orders (user_id, goods_id) VALUES (?, ?)")
            ->execute([$userId, $goodsId]);
    }
    $pdo->commit();
} catch (Exception $e) {
    $pdo->rollBack();
    throw $e;
}

缓存预热

将商品信息加载到Redis,使用原子操作DECR处理库存。避免频繁访问数据库,Lua脚本保证操作原子性。

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->set("goods_stock_{$goodsId}", 100); // 初始化库存

$lua = "
local stock = tonumber(redis.call('get', KEYS[1]))
if stock > 0 then
    redis.call('decr', KEYS[1])
    return 1
end
return 0
";

$result = $redis->eval($lua, ["goods_stock_{$goodsId}"], 1);
if ($result) {
    // 秒杀成功,异步处理数据库
}

请求限流

使用Redis计数器限制单位时间内的请求量,防止系统过载。结合IP和用户ID进行更细粒度的控制。

$key = 'seckill_rate_limit_' . date('YmdHi');
$redis->multi();
$redis->incr($key);
$redis->expire($key, 60);
$redis->exec();

if ($redis->get($key) > 1000) {
    header('HTTP/1.1 429 Too Many Requests');
    exit;
}

异步处理

将秒杀请求放入消息队列(如RabbitMQ),后台消费者顺序处理。实现流量削峰,提高系统吞吐量。

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

$msg = new AMQPMessage(json_encode([
    'user_id' => $userId,
    'goods_id' => $goodsId
]));

$channel->basic_publish($msg, '', 'seckill_queue');
$channel->close();
$connection->close();

防作弊措施

验证用户身份和请求合法性,限制单个用户购买数量。使用隐藏表单令牌防止CSRF攻击。

php秒杀 实现过程

session_start();
$token = md5(uniqid());
$_SESSION['seckill_token'] = $token;

// 在表单中输出
<input type="hidden" name="token" value="<?php echo $token; ?>">

// 提交时验证
if (empty($_POST['token']) || $_POST['token'] !== $_SESSION['seckill_token']) {
    die('非法请求');
}

标签: 过程秒杀
分享给朋友:

相关文章

php评论实现过程

php评论实现过程

实现PHP评论功能的基本过程 数据库设计 创建数据库表存储评论信息,通常包含字段:评论ID、用户ID、内容、发布时间、关联文章ID等。示例SQL: CREATE TABLE comments (…

js实现汉诺塔移动过程

js实现汉诺塔移动过程

汉诺塔问题概述 汉诺塔(Tower of Hanoi)是一个经典的递归问题,目标是将一组盘子从起始柱移动到目标柱,遵循以下规则: 每次只能移动一个盘子。 每次移动时,将最上面的盘子移动到某一柱上。…

php实现过程

php实现过程

PHP 实现过程 PHP 是一种广泛使用的服务器端脚本语言,适用于 Web 开发。以下是 PHP 实现过程的关键步骤和注意事项。 安装 PHP 环境 确保服务器或本地开发环境已安装 PHP。可以通过…

php秒杀功能的实现

php秒杀功能的实现

PHP秒杀功能实现方案 数据库设计 秒杀系统需要高性能数据库设计,核心表包含商品表、订单表和库存表。商品表记录秒杀商品信息,订单表处理交易记录,库存表确保数据一致性。 商品表设计示例: CREAT…

php实现商城秒杀

php实现商城秒杀

PHP实现商城秒杀的核心逻辑 商城秒杀的核心在于高并发场景下的库存准确性和系统稳定性。PHP可以通过以下方案实现: 数据库设计 创建秒杀商品表,包含字段如id、name、stock、start_ti…

商品秒杀实现php

商品秒杀实现php

商品秒杀系统的核心设计 高并发秒杀系统的关键在于解决超卖问题和性能瓶颈。PHP实现需结合缓存、队列、数据库锁等技术。 数据库设计 创建商品表和订单表是基础。商品表需包含库存字段,订单表记录秒杀成功用…