Redis(十一) Redis分布式鎖

2021-09-26 12:00:02 字數 2326 閱讀 5182

為什麼需要使用分布式鎖:因為synchronize和lock是乙個jvm中線程級別的鎖。如何應用部署在多台伺服器上(多個jvm),那synchronize和lock就不起作用了。所以需要分布式鎖來保證符合操作的原子性。

1、基於資料庫:

2、zookeeper分布式鎖(高一致性,效能較差)

3、基於redis等快取分布式鎖(效能好,不保證一致性)

版本一:使用setnx和expire命令實現分布式鎖

#不存在再設值

setnx lock 1

#防止死鎖,設定過期時間

expire lock 10

存在的問題:setnx和 expire不是原子性操作。若setnx後,還沒來得及設定過期時間,服務就掛了。就會造成死鎖

版本二:redis的2.6.12版本後set命令同時支援setnx 和expire:set lock 1 nx ex 10

實現了setnx 和expire的原子性操作。

版本二存在的問題:會誤刪除別人的鎖

1、程序a獲取鎖成功,設定超時時間10s

2、a執行業務期間,由於業務阻塞時間超過10s, 鎖超時自動釋放

3、此時程序b成功獲取鎖,執行業務

4、程序a業務執行完成,釋放鎖,這時候由於a的鎖其實已經超時自動釋放了,所以這時手動釋放的是b的鎖

5、b的鎖已經釋放了,此時c程序也成功獲取到了鎖。

誤刪別人鎖,b和c同時獲取到鎖了。導致鎖的互斥性被破壞。

解決辦法:設定鎖的時候,儲存自己的資訊(lock不能隨便設定),最後只能刪除自己的鎖。

//釋放鎖

}

前面文章介紹重入鎖得原理:為每個鎖關聯乙個獲取計數值和乙個所有者的執行緒。當計數值為0時,該鎖未被任何執行緒持有。當乙個執行緒請求乙個未被持有的鎖時,jvm會記下鎖的持有者和計數值+1 ,如果是同乙個執行緒再次獲取這個鎖時,計數值遞增。當執行緒退出同步**塊時,計數值遞減。當計數值為0時,這個鎖被釋放。

//釋放鎖(計算器==0,直接刪除鎖)

}

由於需要記錄鎖的名稱、持有鎖的執行緒、 持有鎖的執行緒的計數器。所以需要hash資料結構才能完成。

以上**實現的符合操作是非原子性。所以會出現執行緒安全問題。

版本四:使用lua指令碼

使用lua指令碼。將以上邏輯使用lua指令碼實現。然後redis執行lua指令碼是支援原子性的。

這也是面試遇到的問題之一。當正在執行業務的過程中,超過過期時間。鎖自動釋放。其他執行緒便能獲取到鎖。破壞了鎖的互斥性。所以需要保證過期時間大於業務的執行時間。

方案:開啟執行緒,輪詢重新整理過期時間。

//獲取鎖

string result = jedis.set(lockkey, lockvalue, not_exist, seconds, 30);

//獲取鎖成功

if (ok.equals(result)) }}

//業務執行...

//執行完畢,手動釋放鎖

}

以上都屬於自己造輪子。redis推薦使用redisson實現分布式鎖。已經幫我們實現了

後續會在合適的時候分享redisson原始碼解析。這裡給出redisson使用示例:

1、引入依賴

org.redisson

redisson

3.5.0

2、配置

@configuration

public class redissonautoconfiguration

}

3、使用

//通過key獲取lock例項

rlock lock = redisson.getlock("lockname");

//加鎖

boolean result = lock.trylock(-1, 5, timeunit.minutes);

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