redis分布式鎖
分布式鎖的實現方式
1.資料庫樂觀鎖;2. 基於redis的分布式鎖;3. 基於zookeeper的分布式鎖,本篇介紹第二種
使用分布式鎖需要滿足的條件
1:互斥性。在任意時刻,只有乙個客戶端能持有鎖。
2:不會發生死鎖。即使有乙個客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保證後續其他客戶端能加鎖。
3:具有容錯性。只要大部分的redis節點正常執行,客戶端就可以加鎖和解鎖,加鎖和解鎖必須是同乙個客戶端,客戶端自己不能把別人加的鎖給解了。
**示例:
public class redistool
return false;
}}
可以看到,我們加鎖就一行**:jedis.set(string key, string value, string n***, string expx, int time),這個set()方法一共有五個形參:
第乙個為key,我們使用key來當鎖,因為key是唯一的。
第二個為value,我們傳的是requestid,很多童鞋可能不明白,有key作為鎖不就夠了嗎,為什麼還要用到value?原因就是我們在上面講到可靠性時,分布式鎖要滿足第四個條件解鈴還須繫鈴人,通過給value賦值為requestid,我們就知道這把鎖是哪個請求加的了,在解鎖的時候就可以有依據。requestid可以使用uuid.randomuuid().tostring()方法生成。
第三個為n***,這個引數我們填的是nx,意思是set if not exist,即當key不存在時,我們進行set操作;若key已經存在,則不做任何操作;
第四個為expx,這個引數我們傳的是px,意思是我們要給這個key加乙個過期的設定,具體時間由第五個引數決定。
第五個為time,與第四個引數相呼應,代表key的過期時間。
總的來說,執行上面的set()方法就只會導致兩種結果:1. 當前沒有鎖(key不存在),那麼就進行加鎖操作,並對鎖設定個有效期,同時value表示加鎖的客戶端。2. 已有鎖存在,不做任何操作。
心細的童鞋就會發現了,我們的加鎖**滿足我們可靠性裡描述的三個條件。首先,set()加入了nx引數,可以保證如果已有key存在,則函式不會呼叫成功,也就是只有乙個客戶端能持有鎖,滿足互斥性。其次,由於我們對鎖設定了過期時間,即使鎖的持有者後續發生崩潰而沒有解鎖,鎖也會因為到了過期時間而自動解鎖(即key被刪除),不會發生死鎖。最後,因為我們將value賦值為requestid,代表加鎖的客戶端請求標識,那麼在客戶端在解鎖的時候就可以進行校驗是否是同乙個客戶端。由於我們只考慮redis單機部署的場景,所以容錯性我們暫不考慮。
錯誤示例1
比較常見的錯誤示例就是使用jedis.setnx()和jedis.expire()組合實現加鎖,**如下:
public static void wronggetlock1(jedis jedis, string lockkey, string requestid, int expiretime)
}
setnx()方法作用就是set if not exist,expire()方法就是給鎖加乙個過期時間。乍一看好像和前面的set()方法結果一樣,然而由於這是兩條redis命令,不具有原子性,如果程式在執行完setnx()之後突然崩潰,導致鎖沒有設定過期時間。那麼將會發生死鎖。網上之所以有人這樣實現,是因為低版本的jedis並不支援多引數的set()方法。 分布式鎖 使用Redis實現分布式鎖
關於分布式鎖的實現,我的前一篇文章講解了如何使用zookeeper實現分布式鎖。關於分布式鎖的背景此處不再做贅述,我們直接討論下如何使用redis實現分布式鎖。關於redis,筆主不打算做長篇大論的介紹,只介紹下redis優秀的特性。支援豐富的資料型別,如string list map set zs...
使用Redis實現分布式鎖
網上大部分建議都是使用setnx,這個本身沒有什麼問題,因為低版本的redis中,只有這個命令可以互斥的set乙個key。但是隨著redis版本的公升高,提供了更多的命令來更好的滿足我們的需求。set keyvalue ex seconds px milliseconds nx xx 這可和你所知道...
使用redis 實現分布式鎖
在有些需要高可用的場景中,保證併發量的情況下需要使用分布式鎖來做控制,保證應用的可靠性。我們知道jdk提供了一些常用的鎖比如reentrantlock,reentrantreadwritelock,synchronized。對於這些鎖的實現這裡就不詳細介紹了,在使用過程中這些鎖鎖的是物件,在單伺服器...