Redis 用于高效的队列管理和临时缓存,支持每分钟处理数千笔订单的高并发场景

为了支持高并发订单处理,并结合 MySQL 进行持久化,可以将 Redis 用于高效的队列管理和临时缓存,而 MySQL 用于最终数据存储。下面是一个结合 Redis 和 MySQL 的完整示例。

MySQL 表结构

首先,需要定义 MySQL 表结构来存储订单和库存信息。

CREATE TABLE `orders` (
    `id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    `user_id` BIGINT UNSIGNED NOT NULL,
    `product_id` BIGINT UNSIGNED NOT NULL,
    `quantity` INT NOT NULL,
    `status` VARCHAR(50) DEFAULT 'pending',
    `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE `products` (
    `id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    `name` VARCHAR(255) NOT NULL,
    `stock` INT NOT NULL,
    `price` DECIMAL(10, 2) NOT NULL
);

PHP 实现

class OrderProcessing
{
    private $redis;
    private $pdo;
    private $queueName;

    public function __construct($redis, $pdo, $queueName = 'order_queue')
    {
        $this->redis = $redis;
        $this->pdo = $pdo;
        $this->queueName = $queueName;
    }

    /**
     * 提交订单
     */
    public function submitOrder($userId, $productId, $quantity)
    {
        // 先检查库存
        $stock = $this->redis->get("product_stock_$productId");
        
        if ($stock === false) {
            // 如果 Redis 中没有缓存库存,从数据库中读取并缓存
            $stmt = $this->pdo->prepare("SELECT stock FROM products WHERE id = :id");
            $stmt->execute(['id' => $productId]);
            $stock = $stmt->fetchColumn();
            $this->redis->set("product_stock_$productId", $stock);
        }

        if ($stock >= $quantity) {
            // 将订单数据推送到 Redis 队列中
            $orderData = [
                'user_id' => $userId,
                'product_id' => $productId,
                'quantity' => $quantity
            ];
            $this->redis->lpush($this->queueName, json_encode($orderData));

            // 减少 Redis 中的库存
            $this->redis->decrBy("product_stock_$productId", $quantity);

            return "Order submitted successfully.";
        } else {
            return "Insufficient stock.";
        }
    }

    /**
     * 处理订单(消费者)
     */
    public function processOrders()
    {
        while (true) {
            $orderData = $this->redis->rpop($this->queueName);

            if ($orderData) {
                $order = json_decode($orderData, true);
                $this->processOrder($order);
            } else {
                usleep(500000); // 休眠 500ms
            }
        }
    }

    /**
     * 实际处理订单的逻辑
     */
    private function processOrder($order)
    {
        try {
            $this->pdo->beginTransaction();

            // 插入订单记录
            $stmt = $this->pdo->prepare("INSERT INTO orders (user_id, product_id, quantity) VALUES (:user_id, :product_id, :quantity)");
            $stmt->execute([
                'user_id' => $order['user_id'],
                'product_id' => $order['product_id'],
                'quantity' => $order['quantity']
            ]);

            // 更新数据库中的库存
            $stmt = $this->pdo->prepare("UPDATE products SET stock = stock - :quantity WHERE id = :id");
            $stmt->execute([
                'quantity' => $order['quantity'],
                'id' => $order['product_id']
            ]);

            $this->pdo->commit();
        } catch (Exception $e) {
            $this->pdo->rollBack();
            // 将订单重新放回队列或记录日志
            $this->redis->lpush($this->queueName, json_encode($order));
            echo "Failed to process order: " . $e->getMessage() . PHP_EOL;
        }
    }
}

代码详解

  1. 提交订单 (submitOrder)

    • 首先检查 Redis 中是否有该产品的库存。如果没有,则从数据库中读取并缓存到 Redis 中。
    • 如果库存充足,则将订单数据推送到 Redis 队列,并在 Redis 中扣减库存。
  2. 处理订单 (processOrders)

    • 订单处理由消费者进程执行,从 Redis 队列中取出订单数据,并将订单插入数据库,同时更新数据库中的库存。
    • 为了确保数据一致性,使用 MySQL 的事务处理订单和库存的更新。
  3. 实际处理订单的逻辑 (processOrder)

    • 该方法执行插入订单记录和更新库存的具体操作,并确保在出现错误时能够回滚事务并重新处理订单。

优化建议

  1. 多消费者进程

    • 可以启动多个消费者进程来并发处理订单,以提高订单处理速度。
  2. Redis 集群

    • 如果并发量非常大,建议使用 Redis 集群来分散负载。
  3. 异步处理

    • 进一步优化可以将某些任务(如发送确认邮件)放入异步队列中处理,以减轻主订单处理的压力。

此方案利用 Redis 的原子操作和 MySQL 的持久化存储,能够有效支持每分钟数千笔订单的高并发处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值