中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java分布式鎖如何實現

發布時間:2023-03-31 16:51:51 來源:億速云 閱讀:110 作者:iii 欄目:開發技術

這篇“Java分布式鎖如何實現”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Java分布式鎖如何實現”文章吧。

一、分布式鎖介紹

單機多線程: 在 Java 中,我們通常使用 ReetrantLock 類、synchronized 關鍵字這類 本地鎖 來控制一個 JVM 進程內的多個線程對本地共享資源的訪問

Java分布式鎖如何實現

分布式系統: 不同的服務/客戶端通常運行在獨立的 JVM 進程上。如果多個 JVM 進程共享同一份資源的話,使用本地鎖就沒辦法實現資源的互斥訪問了。于是,分布式鎖就誕生了。

舉個例子:系統的訂單服務一共部署了 3 份,都對外提供服務。用戶下訂單之前需要檢查庫存,為了防止超賣,這里需要加鎖以實現對檢查庫存操作的同步訪問。由于訂單服務位于不同的 JVM 進程中,本地鎖在這種情況下就沒辦法正常工作了。我們需要用到分布式鎖,這樣的話,即使多個線程不在同一個 JVM 進程中也能獲取到同一把鎖,進而實現共享資源的互斥訪問。

Java分布式鎖如何實現

一個最基本的分布式鎖需要滿足:

  • 互斥 :任意一個時刻,鎖只能被一個線程持有;

  • 高可用 :鎖服務是高可用的。并且,即使客戶端的釋放鎖的代碼邏輯出現問題,鎖最終一定還是會被釋放,不會影響其他線程對共享資源的訪問。

  • 可重入:一個節點獲取了鎖之后,還可以再次獲取鎖。

二、基于Redis實現分布式鎖

1. 如何基于 Redis 實現一個最簡易的分布式鎖

不論是本地鎖還是分布式鎖,核心都在于==“互斥”==。

在 Redis 中, SETNX 命令是可以幫助我們實現互斥。SETNX即 SET if Not eXists (對應 Java 中的 setIfAbsent 方法),如果 key 不存在的話,才會設置 key 的值。如果 key 已經存在, SETNX 啥也不做。

> SETNX lockKey uniqueValue
(integer) 1
> SETNX lockKey uniqueValue
(integer) 0

釋放鎖的話,直接通過 DEL 命令刪除對應的 key 即可

> DEL lockKey
(integer) 1

為了防止誤刪到其他的鎖,這里我們建議使用 Lua 腳本通過 key 對應的 value(唯一值)來判斷。

選用 Lua 腳本是為了保證解鎖操作的原子性。因為 Redis 在執行 Lua 腳本時,可以以原子性的方式執行,從而保證了鎖釋放操作的原子性。

// 釋放鎖時,先比較鎖對應的 value 值是否相等,避免鎖的誤釋放
if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

Java分布式鎖如何實現

這是一種最簡易的 Redis 分布式鎖實現,實現方式比較簡單,性能也很高效。不過,這種方式實現分布式鎖存在一些問題。就比如應用程序遇到一些問題比如釋放鎖的邏輯突然掛掉,可能會導致鎖無法被釋放,進而造成共享資源無法再被其他線程/進程訪問。

2. 為什么要給鎖設置一個過期時間

主要為了避免鎖無法被釋放

127.0.0.1:6379> SET lockKey uniqueValue EX 3 NX
OK

  • lockKey :加鎖的鎖名;

  • uniqueValue :能夠唯一標示鎖的隨機字符串;

  • NX :只有當 lockKey 對應的 key 值不存在的時候才能 SET 成功;

  • EX :過期時間設置(秒為單位)EX 3 標示這個鎖有一個 3 秒的自動過期時間。與 EX 對應的是 PX(毫秒為單位),這兩個都是過期時間設置。

一定要保證設置指定 key 的值和過期時間是一個原子操作!!! 不然的話,依然可能會出現鎖無法被釋放的問題。

這種解決辦法同樣存在漏洞:

  • 如果操作共享資源的時間大于過期時間,就會出現鎖提前過期的問題,進而導致分布式鎖直接失效

  • 如果鎖的超時時間設置過長,又會影響到性能

3. 如何實現鎖的優雅續期

Redisson 是一個開源的 Java 語言 Redis 客戶端,提供了很多開箱即用的功能,不僅僅包括多種分布式鎖的實現。并且,Redisson 還支持 Redis 單機、Redis Sentinel 、Redis Cluster 等多種部署架構。

Redisson 中的分布式鎖自帶自動續期機制,使用起來非常簡單,原理也比較簡單,其提供了一個專門用來監控和續期鎖的 Watch Dog( 看門狗),如果操作共享資源的線程還未執行完成的話,Watch Dog 會不斷地延長鎖的過期時間,進而保證鎖不會因為超時而被釋放。

Java分布式鎖如何實現

使用方式舉例:

// 1.獲取指定的分布式鎖對象
RLock lock = redisson.getLock("lock");
// 2.拿鎖且不設置鎖超時時間,具備 Watch Dog 自動續期機制
lock.lock();
// 3.執行業務
...
// 4.釋放鎖
lock.unlock();

只有未指定鎖超時時間,才會使用到 Watch Dog 自動續期機制。

// 手動給鎖設置過期時間,不具備 Watch Dog 自動續期機制
lock.lock(10, TimeUnit.SECONDS);

總的來說就是使用Redisson,它帶有自動的續期機制

4. 如何實現可重入鎖

所謂可重入鎖指的是在一個線程中可以多次獲取同一把鎖,比如一個線程在執行一個帶鎖的方法,該方法中又調用了另一個需要相同鎖的方法,則該線程可以直接執行調用的方法即可重入 ,而無需重新獲得鎖。像 Java 中的 synchronized 和 ReentrantLock 都屬于可重入鎖。

可重入分布式鎖的實現核心思路是線程在獲取鎖的時候判斷是否為自己的鎖,如果是的話,就不用再重新獲取了。為此,我們可以為每個鎖關聯一個可重入計數器和一個占有它的線程。當可重入計數器大于 0 時,則鎖被占有,需要判斷占有該鎖的線程和請求獲取鎖的線程是否為同一個。

以上就是關于“Java分布式鎖如何實現”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

唐山市| 金湖县| 柳林县| 崇左市| 宜宾县| 伊春市| 高清| 托里县| 诸暨市| 扬中市| 吕梁市| 武义县| 台东市| 白水县| 茂名市| 漳浦县| 嘉善县| 定安县| 连江县| 咸宁市| 中山市| 静宁县| 莲花县| 兖州市| 昭觉县| 信阳市| 灵寿县| 上犹县| 楚雄市| 南溪县| 神木县| 镇沅| 祁连县| 泸水县| 长泰县| 蒙山县| 云梦县| 卢湾区| 忻州市| 乐都县| 册亨县|