当前位置:首页 > PHP

php 抢购实现思路

2026-02-15 07:50:19PHP

数据库设计

使用InnoDB引擎确保事务支持,创建商品表包含库存字段(如stock),订单表记录抢购成功数据。关键字段需添加索引,如商品ID和用户ID组合索引。

CREATE TABLE `product` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `stock` int(11) NOT NULL COMMENT '库存',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

CREATE TABLE `order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `product_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_product_user` (`product_id`,`user_id`)
) ENGINE=InnoDB;

悲观锁实现

在事务内使用SELECT FOR UPDATE锁定商品记录,确保库存检查与扣减的原子性。需注意事务粒度控制,避免长时间锁表。

$pdo->beginTransaction();
try {
    $stmt = $pdo->prepare('SELECT stock FROM product WHERE id = ? FOR UPDATE');
    $stmt->execute([$productId]);
    $stock = $stmt->fetchColumn();

    if ($stock > 0) {
        $pdo->prepare('UPDATE product SET stock = stock - 1 WHERE id = ?')->execute([$productId]);
        $pdo->prepare('INSERT INTO order (product_id, user_id) VALUES (?, ?)')->execute([$productId, $userId]);
    }
    $pdo->commit();
} catch (Exception $e) {
    $pdo->rollBack();
}

乐观锁实现

通过版本号或时间戳字段实现无锁并发控制。更新时校验版本号,冲突时自动重试或失败。适合并发量中等场景。

php 抢购实现思路

$version = $pdo->query("SELECT version FROM product WHERE id = $productId")->fetchColumn();
$affected = $pdo->exec("UPDATE product SET stock = stock - 1, version = version + 1 
                        WHERE id = $productId AND version = $version");

if ($affected === 0) {
    throw new Exception('抢购失败');
}

缓存预减库存

采用Redis原子操作预减库存,Lua脚本保证操作原子性。实际库存不足时快速返回,减轻数据库压力。

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

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

$res = $redis->eval($lua, ['product_stock_' . $productId], 1);
if ($res === 0) {
    die('已售罄');
}

队列削峰

使用RabbitMQ或Kafka将请求异步化,消费者顺序处理订单。结合令牌桶算法控制处理速率,实现流量整形。

php 抢购实现思路

$channel->queue_declare('seckill', false, true, false, false);
$channel->basic_publish(
    new AMQPMessage(json_encode(['product_id' => $productId, 'user_id' => $userId]), 
    '', 
    'seckill'
);

限流措施

Nginx层实现IP限流,PHP应用层使用Redis计数器限制用户频率。滑动窗口算法统计单位时间请求量。

$key = 'user_limit_' . $userId;
$count = $redis->incr($key);
if ($count === 1) {
    $redis->expire($key, 10);
}
if ($count > 5) {
    die('操作过于频繁');
}

数据一致性

通过定时任务核对Redis与数据库库存差异,引入分布式锁处理超卖。采用本地消息表实现最终一致性。

// 核对脚本示例
$dbStock = $pdo->query("SELECT stock FROM product WHERE id = 1")->fetchColumn();
$redisStock = $redis->get('product_stock_1');
if ($dbStock != $redisStock) {
    // 触发补偿逻辑
}

前端优化

静态资源CDN加速,按钮提交后禁用防止重复点击。倒计时结束前预加载接口,减少网络延迟影响。

document.getElementById('btn').addEventListener('click', function() {
    this.disabled = true;
    fetch('/seckill', {method: 'POST'});
});

标签: 思路php
分享给朋友:

相关文章

Vue实现思路

Vue实现思路

Vue 实现思路 Vue 是一种流行的前端框架,用于构建用户界面。其核心思想是通过数据驱动和组件化开发,使开发过程更加高效和可维护。以下是 Vue 实现的一些关键思路: 数据驱动视图 Vue 采用响…

vue路由实现思路

vue路由实现思路

Vue 路由实现思路 Vue 路由的核心是通过 Vue Router 库实现的单页面应用(SPA)路由管理。以下是关键实现思路和步骤: 安装 Vue Router 通过 npm 或 yarn 安装…

php实现打印功能

php实现打印功能

PHP实现打印功能的方法 在PHP中实现打印功能可以通过多种方式完成,包括直接输出到浏览器、生成PDF文件、调用打印机接口等。以下是几种常见的方法: 直接输出HTML内容 PHP可以通过echo或…

php记住密码怎么实现

php记住密码怎么实现

使用Cookie实现记住密码功能 在PHP中,可以通过设置Cookie来记住用户的登录状态。以下是一个简单的实现方式: // 用户登录验证成功后 if ($login_success) {…

php实现注册

php实现注册

注册功能实现步骤 数据库准备 创建用户表,包含字段如id、username、password、email等。示例SQL: CREATE TABLE users ( id INT AUTO_I…

php实现mysql

php实现mysql

PHP 连接 MySQL 的基本方法 PHP 提供了多种方式与 MySQL 数据库进行交互,以下是最常用的几种方法。 使用 MySQLi 扩展 MySQLi 是 MySQL 的改进扩展,支持面…