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

php利用redis实现秒杀

php利用redis实现秒杀

PHP 利用 Redis 实现秒杀功能 秒杀场景的特点是高并发、低库存,Redis 因其高性能和原子性操作,成为实现秒杀系统的理想工具。以下是核心实现方法: 使用 Redis 原子操作控制库存 通过…

php实现商城秒杀

php实现商城秒杀

PHP实现商城秒杀的核心逻辑 商城秒杀的核心在于高并发场景下的库存控制和数据一致性。PHP可通过以下方案实现: 数据库设计优化 创建独立的秒杀商品表,包含字段如id、product_id、stock…

秒杀php实现

秒杀php实现

秒杀系统核心设计要点 高并发、低延迟、数据一致性是秒杀系统的核心挑战。PHP实现需结合缓存、队列、限流等技术确保系统稳定。 数据库优化 使用InnoDB引擎并优化事务隔离级别。商品库存字段需添加无符…

js秒杀实现

js秒杀实现

秒杀系统核心实现思路 高并发秒杀系统的核心在于解决超卖问题和性能瓶颈,需结合前端优化、后端限流、缓存预热、异步处理等技术。 前端优化策略 静态资源CDN加速,减少主站请求压力 按钮倒计时与点击防抖,…

秒杀 js 实现

秒杀 js 实现

秒杀功能的实现要点 前端实现秒杀功能需要处理高并发、时间同步、防刷等问题。以下是基于JavaScript的核心实现逻辑: 倒计时功能 使用定时器实现秒杀倒计时,需确保与服务器时间同步: f…