Redis分布式鎖

2021-09-07 17:55:29 字數 2818 閱讀 4780

1、synchronized處理併發的缺點?

(1)速度比較慢,無法做到細粒度的控制。

(2)只適合單機的情況,不適合集群。

2、分布式鎖的實現方案

分布式鎖一般有三種實現方式:

(1). 資料庫樂觀鎖;

(2) 基於redis的分布式鎖;

(3). 基於zookeeper的分布式鎖

3、分布式鎖的保障條件

為了確保分布式鎖可用,我們至少要確保鎖的實現同時滿足以下四個條件:

(1)互斥性。在任意時刻,只有乙個客戶端能持有鎖。

(2)不會發生死鎖。即使有乙個客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保證後續其他客戶端能加鎖。

(3)具有容錯性。只要大部分的redis節點正常執行,客戶端就可以加鎖和解鎖。

(4)解鈴還須繫鈴人。加鎖和解鎖必須是同乙個客戶端,客戶端自己不能把別人加的鎖給解了。

4、基於redis的分布式鎖實現(商品秒殺場景的解決方案)

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

1)setnx(set if not exists)將 key 的值設為 value ,當且僅當 key 不存在。若給定的 key 已經存在,則 setnx 不做任何動作。

setnx 是『set if not exists』(如果不存在,則 set)的簡寫。

返回值:

設定成功,返回 

1 。返回1,則該客戶端獲得鎖,把lock.foo的鍵值設定為時間值表示該鍵已被鎖定,該客戶端最後可以通過del lock.foo來釋放該鎖

設定失敗,返回 

0 。返回0,表明該鎖已被其他客戶端取得,這時我們可以先返回或進行重試等對方完成或等待鎖超時。

2)getset(先get再set,get舊值,set新值)

將給定 key 的值設為 value ,並返回 key 的舊值(old value)。

當 key 存在但不是字串型別時,返回乙個錯誤。

返回值:

返回給定 

key 的舊值。

當  key 沒有舊值時,也即是, 

key 不存在時,返回 

nil 。

描述:set()加入了nx引數,可以保證如果已有key存在,則函式不會呼叫成功,也就是只有乙個客戶端能持有鎖,滿足互斥性。

其次,由於我們對鎖設定了過期時間,即使鎖的持有者後續發生崩潰而沒有解鎖,鎖也會因為到了過期時間而自動解鎖(即key被刪除),不會發生死鎖。

面試題:redis分布式鎖如何實現的:

主要利用setnx和getset命令來實現的。

setnx主要是利用保證乙個客戶端可以獲取到該鎖即保證互斥性。

我們會在setnx設定key的value值設定乙個時間,這個時間是我們可以設定為當前時間+過期時間,即總共執行緒可以保留該鎖的時間。

如果該時間過期,則另外有執行緒訪問的時候,則利用getset方法來進行獲取原來的時間和設定新的value值,判斷下是否可以獲取該鎖。如果獲取了該鎖則下乙個執行緒進來的時候就不可以獲取該鎖了。這樣避免了死鎖同時也可以防止多個執行緒同時獲取鎖。

主要redis的setnx和getset這兩個命令。

主要有兩步操作:加鎖和解鎖

初步計畫在此段**新增加鎖和解鎖的功能:

redis的分布式鎖**:

加鎖和解鎖是在乙個類中:

加鎖:

解鎖:

處理併發的加鎖和解鎖後的業務**:

問題:1、為什麼不直接使用expire設定超時時間,而將時間的毫秒數其作為value放在redis中?

redis expire 命令用於設定 key 的過期時間。key 過期後將不再可用。

expirekey_name   time_in_seconds  例如:

expire runooobkey 60,設定60s後過期。

答案:假如在setnx後,redis崩潰了,expire就沒有執行,結果就是死鎖了,鎖永遠不會超時。

2、為什麼前面的鎖已經超時了,還要用getset去設定新的時間戳的時間獲取舊的值,然後和外面的判斷超時時間的時間戳比較呢?

因為是分布式的環境下,可以在前乙個鎖失效的時候,有兩個程序進入到鎖超時的判斷。如:

c0超時了,還持有鎖,c1/c2同時請求進入了方法裡面

c1/c2獲取到了c0的超時時間

c1使用getset方法

c2也執行了getset方法

假如我們不加 oldvaluestr.equals(currentvaluestr) 的判斷,將會c1/c2都將獲得鎖,加了之後,能保證c1和c2只能乙個能獲得鎖,乙個只能繼續等待。

注意:這裡可能導致超時時間不是其原本的超時時間,c1的超時時間可能被c2覆蓋了,但是他們相差的毫秒及其小,這裡忽略了。

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不存在。如給定的...