关联链接 http://blog.shuxuemi.cn/web/index/detail/19

首先库存信息使用redis存储;在防并发操作时(秒杀减库存),一般由于check和set操作不是原子操作,导致脏数据。 从redis2.6开始可以使用lua脚本的形式,配合redis的单进程单线程模型,完成check和set原子操作

function createOrder($product_id, $num, $opt = [])
{
    //根据商品id生成具体的key,key中存的是商品的库存数量
    $product_key = "product_stock_num:" . $product_id;
    $script = <<<PRODUCT_SCRIPT
local key = ARGV[1]
local num = ARGV[2]
local current_stock = redis.call('get', key)
if (current_stock >= num ) then
    local new_stock = current_stock - num
    redis.call('set', key, new_stock)
    return new_stock
else
    return -1
end
PRODUCT_SCRIPT;
    $redis = new \Redis();
    $redis->connect("127.0.0.1");
    $script_hash = $redis->script("load", $script);
    //当脚本执行失败会返回false,失败原因一般为key不存在
    $flag = $redis->evalSha($script_hash, [$product_key, $num], 0);
    if ($flag !== false && $flag !== -1) {
        return true;
    }
    return false;
}
createOrder(1, 1);