当前位置:首页 > PHP

php抢购实现

2026-01-29 22:31:01PHP

高并发抢购系统的实现要点

PHP实现抢购功能需要解决高并发下的数据一致性和系统性能问题。核心在于库存控制、请求限流和分布式锁的应用。

数据库设计优化

使用InnoDB引擎并建立合适索引,商品表需包含库存字段并设置无符号整型防止超卖。单独设计订单表关联商品ID和用户ID。

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

CREATE TABLE `orders` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `goods_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

乐观锁实现方案

通过版本号或条件更新实现乐观锁控制。在更新库存时添加库存数量条件,确保不会出现负库存。

php抢购实现

$pdo->beginTransaction();
$stmt = $pdo->prepare("UPDATE goods SET stock = stock - 1 WHERE id = ? AND stock > 0");
$stmt->execute([$goods_id]);
if ($stmt->rowCount() > 0) {
    // 生成订单
    $order_stmt = $pdo->prepare("INSERT INTO orders(goods_id, user_id) VALUES(?, ?)");
    $order_stmt->execute([$goods_id, $user_id]);
    $pdo->commit();
} else {
    $pdo->rollBack();
    throw new Exception('库存不足');
}

Redis分布式锁应用

使用SETNX命令实现分布式锁,防止重复请求。设置锁过期时间避免死锁,采用Lua脚本保证原子性。

$redis = new Redis();
$lockKey = 'goods_' . $goods_id;
$randomValue = uniqid();

// 获取锁
if ($redis->set($lockKey, $randomValue, ['NX', 'EX' => 10])) {
    try {
        // 处理抢购逻辑
    } finally {
        // Lua脚本保证原子删除
        $script = 'if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end';
        $redis->eval($script, [$lockKey, $randomValue], 1);
    }
}

请求限流策略

使用Redis实现计数器限流,针对用户ID或IP进行访问频率控制。滑动时间窗口算法能更精确控制单位时间请求量。

php抢购实现

$redisKey = 'rate_limit:' . $user_id;
$now = time();
$windowSize = 60; // 60秒窗口

$redis->multi();
$redis->zAdd($redisKey, $now, uniqid());
$redis->zRemRangeByScore($redisKey, 0, $now - $windowSize);
$redis->expire($redisKey, $windowSize);
$count = $redis->zCard($redisKey);
$redis->exec();

if ($count > 100) { // 限制每分钟100次请求
    header('HTTP/1.1 429 Too Many Requests');
    exit;
}

异步处理方案

采用消息队列将下单请求异步化,前端显示排队中状态。RabbitMQ或Redis的List结构可实现简单队列。

// 生产者
$redis->rPush('order_queue', json_encode([
    'user_id' => $user_id,
    'goods_id' => $goods_id,
    'time' => time()
]));

// 消费者
while (true) {
    $data = $redis->blPop('order_queue', 30);
    if ($data) {
        $orderInfo = json_decode($data[1], true);
        // 处理订单逻辑
    }
}

缓存预热与库存分段

活动开始前预热Redis缓存,将库存分为多段减少竞争。使用Redis的DECR原子操作扣减分段库存。

// 预热10个库存段
for ($i = 0; $i < 10; $i++) {
    $redis->set('goods_stock_segment_' . $goods_id . '_' . $i, 10);
}

// 随机选择分段扣减
$segment = mt_rand(0, 9);
$remaining = $redis->decr('goods_stock_segment_' . $goods_id . '_' . $segment);
if ($remaining >= 0) {
    // 扣减成功
}

服务降级预案

准备降级策略当系统压力过大时,可关闭非核心功能。使用配置中心实时切换降级状态,前端展示友好提示。

if ($configCenter->get('degrade_mode')) {
    header('HTTP/1.1 503 Service Unavailable');
    echo json_encode(['code' => 503, 'msg' => '系统繁忙请稍后再试']);
    exit;
}

标签: php
分享给朋友:

相关文章

php 购物车实现

php 购物车实现

数据库设计 购物车功能通常需要设计数据库表存储商品和用户信息。常见的表包括products(商品表)、users(用户表)和cart(购物车表)。cart表通常包含字段:id(主键)、user_id(…

php 实现购物车

php 实现购物车

PHP 实现购物车功能 购物车功能是电子商务网站的核心部分,可以通过 PHP 和 Session 或数据库来实现。以下是两种常见的实现方式: 使用 Session 存储购物车数据 Sessi…

php实现即时通讯

php实现即时通讯

PHP 实现即时通讯的方案 即时通讯(IM)可以通过多种方式实现,PHP 作为服务器端语言,通常需要结合前端技术(如 WebSocket、AJAX)或第三方服务来实现实时通信。以下是几种常见的实现方式…

php 无限分类的实现

php 无限分类的实现

无限分类的实现方法 无限分类通常用于构建树形结构数据,如商品分类、多级菜单等。以下是几种常见的实现方式: 邻接列表模型(Adjacency List) 邻接列表是最简单的实现方式,通过在每个节点中存…

php 实现评论

php 实现评论

实现 PHP 评论功能 数据库设计 创建数据库表存储评论数据,通常包含以下字段: id:评论唯一标识 user_id:用户ID content:评论内容 created_at:评论时间 parent…

php实现多态

php实现多态

多态的概念 多态是面向对象编程的三大特性之一,指同一个方法在不同类中有不同实现方式。PHP通过继承和接口实现多态。 通过继承实现多态 父类定义方法,子类重写该方法实现不同行为: class…