新版redis分布式鎖

2021-09-24 00:00:21 字數 2491 閱讀 9403

**

不具有原子性操作的加鎖和解鎖都有可能出現問題。

正確示例(需要比較新版本的redis才行):

publicclassredistool

returnfalse;

}

}

錯誤示例1

比較常見的錯誤示例就是使用jedis.setnx()和jedis.expire()組合實現加鎖,**如下:

publicstaticvoidwronggetlock1(jedis jedis, string lockkey, string requestid, intexpiretime)

}

setnx()方法作用就是set if not exist,expire()方法就是給鎖加乙個過期時間。乍一看好像和前面的set()方法結果一樣,然而由於這是兩條redis命令,不具有原子性,如果程式在執行完setnx()之後突然崩潰,導致鎖沒有設定過期時間。那麼將會發生死鎖。網上之所以有人這樣實現,是因為低版本的jedis並不支援多引數的set()方法。

錯誤示例2

這一種錯誤示例就比較難以發現問題,而且實現也比較複雜。實現思路:使用jedis.setnx()命令實現加鎖,其中key是鎖,value是鎖的過期時間。執行過程:1. 通過setnx()方法嘗試加鎖,如果當前鎖不存在,返回加鎖成功。2. 如果鎖已經存在則獲取鎖的過期時間,和當前時間比較,如果鎖已經過期,則設定新的過期時間,返回加鎖成功。**如下:

publicstaticbooleanwronggetlock2(jedis jedis, string lockkey, intexpiretime)

// 如果鎖存在,獲取鎖的過期時間

string currentvaluestr = jedis.get(lockkey);

if(currentvaluestr != null&& long.parselong(currentvaluestr) < system.currenttimemillis())

}

// 其他情況,一律返回加鎖失敗

returnfalse;

}

那麼這段**問題在**?1. 由於是客戶端自己生成過期時間,所以需要強制要求分布式下每個客戶端的時間必須同步。 2. 當鎖過期的時候,如果多個客戶端同時執行jedis.getset()方法,那麼雖然最終只有乙個客戶端可以加鎖,但是這個客戶端的鎖的過期時間可能被其他客戶端覆蓋。3. 鎖不具備擁有者標識,即任何客戶端都可以解鎖。

publicclassredistool

returnfalse;

}

}

首先獲取鎖對應的value值,檢查是否與requestid相等,如果相等則刪除鎖(解鎖)

eval()方法可以確保原子性

錯誤示例1

最常見的解鎖**就是直接使用jedis.del()方法刪除鎖,這種不先判斷鎖的擁有者而直接解鎖的方式,會導致任何客戶端都可以隨時進行解鎖,即使這把鎖不是它的。

3publicstaticvoidwrongreleaselock1(jedis jedis, string lockkey)

錯誤示例2

這種解鎖**乍一看也是沒問題,甚至我之前也差點這樣實現,與正確姿勢差不多,唯一區別的是分成兩條命令去執行,**如下:

publicstaticvoidwrongreleaselock2(jedis jedis, string lockkey, string requestid)

}

如**注釋,問題在於如果呼叫jedis.del()方法的時候,這把鎖已經不屬於當前客戶端的時候會解除他人加的鎖。那麼是否真的有這種場景?答案是肯定的,比如客戶端a加鎖,一段時間之後客戶端a解鎖,在執行jedis.del()之前,鎖突然過期了,此時客戶端b嘗試加鎖成功,然後客戶端a再執行del()方法,則將客戶端b的鎖給解除了。

redis分布式鎖

redis分布式鎖 直接上 我寫了四個redis分布式鎖的方法,大家可以提個意見 第一種方法 redis分布式鎖 param timeout public void lock long timeout thread.sleep 100 catch exception e override publi...

Redis分布式鎖

分布式鎖一般有三種實現方式 1.資料庫樂觀鎖 2.基於redis的分布式鎖 3.基於zookeeper的分布式鎖.首先,為了確保分布式鎖可用,我們至少要確保鎖的實現同時滿足以下四個條件 互斥性。在任意時刻,只有乙個客戶端能持有鎖。不會發生死鎖。即使有乙個客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保...

redis分布式鎖

使用redis的setnx命令實現分布式鎖 redis為單程序單執行緒模式,採用佇列模式將併發訪問變成序列訪問,且多個客戶端對redis的連線並不存在競爭關係。redis的setnx命令可以方便的實現分布式鎖。setnx key value 將key的值設為value,當且僅當key不存在。如給定的...