當前位置:
首頁 > 知識 > Redis分散式鎖的try-with-resources實現

Redis分散式鎖的try-with-resources實現

一、簡介

在當今這個時代,單體應用(standalone)已經很少了,java提供的synchronized已經不能滿足需求,大家自然

而然的想到了分散式鎖。談到分散式鎖,比較流行的方法有3中:

基於資料庫實現的

基於redis實現的

基於zookeeper實現的今天我們重點說一下基於redis的分散式鎖,redis分散式鎖的實現我們可以參照redis的官方文檔。

實現Redis分散式鎖的最簡單的方法就是在Redis中創建一個key,這個key有一個失效時間(TTL),以保證鎖最終會被自動釋放掉。當客戶端釋放資源(解鎖)的時候,會刪除掉這個key。

獲取鎖使用命令:

SET resource_name my_random_value NX PX 30000

這個命令僅在不存在key的時候才能被執行成功(NX選項),並且這個key有一個30秒的自動失效時間(PX屬性)。這個key的值是「my_random_value」(一個隨機值),

這個值在所有的客戶端必須是唯一的,所有同一key的獲取者(競爭者)這個值都不能一樣。

value的值必須是隨機數主要是為了更安全的釋放鎖,釋放鎖的時候使用腳本告訴Redis:只有key存在並且存儲的值和我指定的值一樣才能告訴我刪除成功。

可以通過以下Lua腳本實現:

if redis.call(get,KEYS[1]) == ARGV[1] then return redis.call(del,KEYS[1])else return 0end

使用這種方式釋放鎖可以避免刪除別的客戶端獲取成功的鎖。舉個例子:客戶端A取得資源鎖,但是緊接著被一個其他操作阻塞了,當客戶端A運行完畢其他操作後要釋放鎖時,

原來的鎖早已超時並且被Redis自動釋放,並且在這期間資源鎖又被客戶端B再次獲取到。如果僅使用DEL命令將key刪除,那麼這種情況就會把客戶端B的鎖給刪除掉。

使用Lua腳本就不會存在這種情況,因為腳本僅會刪除value等於客戶端A的value的key(value相當於客戶端的一個簽名)。

這種方法已經足夠安全,如果擔心redis故障轉移時,鎖失效的問題,請參照Redis官方文檔中的RedLock,這裡不做具體討論。

二、try-with-resources的實現

知道了Redis鎖的實現原理,我們再來看看如何實現。其實關鍵的步驟只有兩步:

獲取鎖;

釋放鎖;大家在寫程序的時候是不是總忘記釋放鎖呢?就像以前對流操作時,忘記了關閉流。從java7開始,加入了try-with-resources的方式,它可以

自動的執行close()方法,釋放資源,再也不用寫finally塊了。我們就按照這種思路編寫Redis鎖,在具體寫代碼之前,我們先談談

Redis的客戶端,Redis的客戶端官方推薦有3種:

Jedis;

Lecttuce;

Redisson;Redis官方比較推薦Redisson,但是Spring-data中並沒有這種方式,Spring-Data-Redis支持Jedis和Lecttuce兩種方式。

國內用的比較多的是Jedis,但是Spring-Data默認用Lecttuce。不管那麼多了,直接用Spring-Boot,配置好連接,直接使用就好了。

Redis鎖的try-with-resources實現:

{{1}}

只要實現了Closeable介面,並重寫了close()方法,就可以使用try-with-resources的方式了。

具體的使用代碼如下:

這樣我們就不用關心鎖的釋放問題了。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 千鋒JAVA開發學院 的精彩文章:

分散式服務介面請求的順序性
簡單嘗試Spring Cloud Gateway

TAG:千鋒JAVA開發學院 |