關聯鏈接 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);