Redis 分佈式鎖 解決集羣環境下屢次定時任務執行

先了解Set參數

SET key value [EX seconds] [PX milliseconds] [NX|XX]html

將字符串值value關聯到keynode

若是key 有值, SET 就覆寫舊值,無視類型。

對於某個本來帶有生存時間(TTL)的鍵來講, 當SET命令成功在這個鍵上執行時, 這個鍵原有的 TTL 將被清除。redis

可選參數bash

SET
命令的行爲能夠經過一系列參數來修改:

  • EX second :設置鍵的過時時間爲 second 秒。 SET key value EX second  效果等同  SETEX key second value
  • PX millisecond :設置鍵的過時時間爲 millisecond 毫秒。 SET key value PX millisecond
    效果等同於PSETEX key millisecond value。
  • NX :只在鍵不存在時,纔對鍵進行設置操做。 SET key value NX  效果等同於  SETNX key value
  • XX :只在鍵已經存在時,纔對鍵進行設置操做。
返回值:

在 Redis 2.6.12 版本之前, 數據結構

SET
命令老是返回  OK

從 Redis 2.6.12 版本開始,
SET
在設置操做成功完成時,才返回 OK
若是設置了 NX 或者  XX,但由於條件沒達到而形成設置操做未執行,那麼命令返回空批量回復(NULL Bulk Reply)。

setnx

鎖在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

爲了解決這個問題,咱們能夠把超時時間設置跟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的,我就不該該對它進行任何操做。

相關文章
相關標籤/搜索