当前位置:首页 > PHP

php队列实现抢购

2026-02-16 03:33:40PHP

PHP队列实现抢购方案

抢购场景下高并发容易导致超卖、数据库崩溃等问题。使用队列系统能有效缓解压力,以下是基于PHP的常见实现方案:

使用Redis队列

Redis的List结构适合作为轻量级队列,处理抢购请求:

// 初始化Redis连接
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

// 抢购请求入队
$productId = 1001;
$userId = mt_rand(1000,9999);
$redis->lPush('seckill_queue', json_encode(['user_id'=>$userId, 'product_id'=>$productId]));

// 后台进程消费队列
while(true) {
    $data = $redis->rPop('seckill_queue');
    if($data) {
        $order = json_decode($data, true);
        processOrder($order['user_id'], $order['product_id']);
    }
    usleep(100000); // 0.1秒间隔
}

数据库事务+乐观锁

队列处理后端配合数据库保证数据一致性:

php队列实现抢购

function processOrder($userId, $productId) {
    $pdo->beginTransaction();
    try {
        // 查询库存(加锁)
        $stmt = $pdo->prepare("SELECT stock FROM products WHERE id=? FOR UPDATE");
        $stmt->execute([$productId]);
        $stock = $stmt->fetchColumn();

        if($stock > 0) {
            // 减库存
            $pdo->prepare("UPDATE products SET stock=stock-1 WHERE id=?")->execute([$productId]);
            // 创建订单
            $pdo->prepare("INSERT INTO orders(...) VALUES(...)")->execute([...]);
            $pdo->commit();
            return true;
        }
        $pdo->rollBack();
        return false;
    } catch(Exception $e) {
        $pdo->rollBack();
        return false;
    }
}

使用专业队列系统

对于大规模抢购,建议采用专业队列服务:

  1. RabbitMQ方案
    
    // 生产者
    $connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
    $channel = $connection->channel();
    $channel->queue_declare('seckill', false, true, false, false);
    $msg = new AMQPMessage(json_encode($orderData));
    $channel->basic_publish($msg, '', 'seckill');

// 消费者 $callback = function($msg) { processOrder(json_decode($msg->body, true)); $msg->ack(); }; $channel->basic_consume('seckill', '', false, false, false, false, $callback);

php队列实现抢购


2. Kafka方案
```php
$producer = new RdKafka\Producer();
$producer->addBrokers("kafka:9092");
$topic = $producer->newTopic("seckill");
$topic->produce(RD_KAFKA_PARTITION_UA, 0, json_encode($orderData));

预减库存+异步确认

前端展示与实际库存分离的方案:

// 使用Redis原子操作预减库存
$redis->watch('seckill_stock');
$stock = $redis->get('seckill_stock');
if($stock > 0) {
    $redis->multi();
    $redis->decr('seckill_stock');
    $redis->lPush('seckill_queue', $orderData);
    $redis->exec();
    echo '抢购排队中';
} else {
    echo '已售罄';
}

防刷策略

结合队列需要增加安全措施:

  • 用户频率限制(Redis计数器)
  • 验证码验证
  • 排队进度查询接口
  • 订单超时释放库存

这种架构将瞬时高峰请求转为异步处理,数据库压力降低90%以上。实际部署时需要根据业务规模选择合适队列方案,配合负载均衡和多节点部署。

标签: 队列php
分享给朋友:

相关文章

php实现文件下载

php实现文件下载

PHP 实现文件下载的方法 使用 header() 函数强制下载 设置正确的 HTTP 头信息,强制浏览器下载文件而不是直接打开。 $file = 'path/to/file.pdf'; if (f…

vue实现队列

vue实现队列

Vue 实现队列功能 在 Vue 中实现队列功能,可以利用数组的 push 和 shift 方法模拟队列的先进先出(FIFO)特性。以下是一个简单的实现示例: <template>…

php实现增删改查

php实现增删改查

以下是在PHP中实现增删改查(CRUD)操作的详细方法,以MySQL数据库为例: 数据库连接配置 创建config.php文件存储数据库连接信息: <?php $host = 'localh…

php实现接口

php实现接口

PHP 实现接口的方法 在 PHP 中,接口(Interface)用于定义一组方法的规范,而不实现具体功能。类可以实现一个或多个接口,并必须实现接口中定义的所有方法。 定义接口 接口使用 inter…

php实现一个

php实现一个

PHP 实现一个简单的计算器 创建一个基本的计算器,支持加、减、乘、除运算。以下是一个完整的实现代码示例: <?php $result = ""; if ($_SERVER["REQUEST_…

php 无限分类的实现

php 无限分类的实现

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