背景說明
在程序開發過程中,通常會遇到需要獨占式的訪問一些資源的情形,比如商品秒殺時扣減庫存。這時就需要對資源加鎖。實現鎖的方式有很多,比如數據庫鎖、文件鎖等等。本文簡單介紹PHP中使用redis來實現加鎖和解鎖。實現方式參考了redis官方文檔。
示例代碼
代碼環境:單redis實例,PHP5.6及以上,且需開啟redis擴展
$redis = new \Redis();
$redis->connect('127.0.0.1');
$lockKey = 'lock_key';
$randValue = rand(10000, 99999);
//lock
$lock = $redis->set($lockKey, $randValue, ['NX', 'EX'=>1]);
if($lock) {
//do something
//unlock
$script = '
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
';
$redis->eval($script, [$lockKey, $randValue], 1);
}
代碼說明
這段代碼會在資源未被鎖定(NX選項)時獲取鎖,同時設定了1s的過期時間(EX)選項,可在代碼出錯或超時情況下自動釋放鎖。值被設定為一個隨機數,且執行lua腳本來解鎖,就不會誤釋放其它用戶加的鎖。
分布式鎖的實現可參考 https://redis.io/topics/distlock。