SET key value [EX seconds] [PX milliseconds] [NX|XX]html
將字符串值value關聯到keynode
對於某個本來帶有生存時間(TTL)的鍵來講, 當SET命令成功在這個鍵上執行時, 這個鍵原有的 TTL 將被清除。redis
可選參數bash
命令的行爲能夠經過一系列參數來修改:鎖在redis中最簡單的數據結構就是string。最先的時候,上鎖的操做通常使用setnx,這個命令是當鎖不存在的時候set一個val,或許你還會記得使用expire來增長鎖的過時,解鎖操做就是使用del命令,代碼以下:
app
if(redis.setnx('node:lock', 1)){
redis.expire('node:lock',10);
// ...todo
redis.del('node:lock')
}
}複製代碼
問題就在於setnx和expire中間若是遇到crash等行爲,可能這個lock就不會被釋放了
ui
爲了解決這個問題,咱們能夠把超時時間設置跟set操做放在一塊兒
spa
if(redis.set('node:lock',1, 'nx', 'ex', 10)){
// ...todo
redis.del('node:lock')
}
}複製代碼
獲取鎖的機制是對了,可是刪除鎖的機制直接使用del是不對的。由於有可能致使誤刪別人的鎖的狀況。code
好比,這個鎖我上了10s,可是我處理的時間比10s更長,到了10s,這個鎖自動過時了,被別人取走了,而且對它從新上鎖了。那麼這個時候,我再調用del就是刪除別人創建的鎖了。cdn
終極版:
function lock(lockName,lockTimeout)){
let lockKey=lockName+':lock';
let lockValue=new Date().getTime();
if(redis.set(lockKey,lockValue, 'nx', 'ex', lockTimeout)){
return lockValue;
}
return null;
}
function unlock(lockName, lockValue)){
let lockKey=lockName+':lock';
if(redis.get(lockKey)===lockValue){ redis.del(lockName)
return true;
}}
複製代碼
這裏的lockValue是一個時間戳,當lock的時候,往redis的存儲這個時間戳,unlock的時候,先get一下lock中的值,若是和我要刪除的值是一致的,說明這個鎖是以前我set的,不然的話,說明這個鎖已通過期,是別人set的,我就不該該對它進行任何操做。