以下是一个使用乐观锁的简单示例代码,演示如何在PHP中使用Redis进行商品秒杀并防止超卖:


<?php

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

$productKey = 'product_stock';
$userId = 'user123';
$purchaseQuantity = 1;

// 开始秒杀
if (seckillProduct($productKey, $userId, $purchaseQuantity)) {
    echo "秒杀成功!\n";
} else {
    echo "秒杀失败,库存不足或已购买过!\n";
}

function seckillProduct($productKey, $userId, $quantity)
{
    global $redis;

    // 使用 WATCH 监视 product_stock 键
    $redis->watch($productKey);

    // 获取当前商品库存
    $stock = (int)$redis->get($productKey);

    // 检查库存是否足够
    if ($stock >= $quantity) {
        // 开启事务
        $redis->multi();

        // 减少库存
        $redis->decrby($productKey, $quantity);

        // 模拟生成订单等其他操作
        generateOrder($userId, $quantity);

        // 提交事务
        $result = $redis->exec();

        // 检查事务执行结果
        if ($result !== false) {
            return true; // 秒杀成功
        }
    }

    // 取消 WATCH,事务未执行
    $redis->unwatch();

    return false; // 秒杀失败
}

function generateOrder($userId, $quantity)
{
    // 此处可以添加生成订单等相关操作的代码,示例中只输出信息
    echo "生成订单:用户ID {$userId} 购买数量 {$quantity}\n";
}

在这个示例中,seckillProduct 函数使用了乐观锁的概念。首先,它使用 WATCH 命令监视商品库存键。然后,它检查库存是否足够,如果足够,就开始一个事务,减少库存并执行其他操作(例如生成订单)。最后,使用 EXEC 提交事务,如果提交成功,说明秒杀操作成功,否则说明库存不足或者在监视期间发生了并发操作,需要重试或处理失败。

请注意,这只是一个简单的示例,实际应用中可能需要更复杂的逻辑和错误处理。在高并发环境中,还需要考虑性能和并发控制,可能需要进一步优化和测试。

Last modification:December 27, 2023
如果觉得我的文章对你有用,请随意赞赏