亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java分布式鎖由淺入深介紹

 更新時間:2023年03月30日 09:25:51   作者:kazuhura  
這篇文章主要介紹了Java分布式鎖,數(shù)據(jù)庫實(shí)現(xiàn)分布式鎖方式比較多,如悲觀鎖(查詢時增加for?update)、樂觀鎖(通過version字段)、增加一個表記錄鎖信息等。因為依賴于數(shù)據(jù)庫,比較好理解,但是也存在一些問題

一、分布式鎖介紹

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

分布式系統(tǒng): 不同的服務(wù)/客戶端通常運(yùn)行在獨(dú)立的 JVM 進(jìn)程上。如果多個 JVM 進(jìn)程共享同一份資源的話,使用本地鎖就沒辦法實(shí)現(xiàn)資源的互斥訪問了。于是,分布式鎖就誕生了。

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

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

  • 互斥 :任意一個時刻,鎖只能被一個線程持有;
  • 高可用 :鎖服務(wù)是高可用的。并且,即使客戶端的釋放鎖的代碼邏輯出現(xiàn)問題,鎖最終一定還是會被釋放,不會影響其他線程對共享資源的訪問。
  • 可重入:一個節(jié)點(diǎn)獲取了鎖之后,還可以再次獲取鎖。

二、基于Redis實(shí)現(xiàn)分布式鎖

1. 如何基于 Redis 實(shí)現(xiàn)一個最簡易的分布式鎖

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

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

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

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

> DEL lockKey
(integer) 1

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

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

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

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

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

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

127.0.0.1:6379> SET lockKey uniqueValue EX 3 NX
OK

  • lockKey :加鎖的鎖名;
  • uniqueValue :能夠唯一標(biāo)示鎖的隨機(jī)字符串;
  • NX :只有當(dāng) lockKey 對應(yīng)的 key 值不存在的時候才能 SET 成功;
  • EX :過期時間設(shè)置(秒為單位)EX 3 標(biāo)示這個鎖有一個 3 秒的自動過期時間。與 EX 對應(yīng)的是 PX(毫秒為單位),這兩個都是過期時間設(shè)置。

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

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

  • 如果操作共享資源的時間大于過期時間,就會出現(xiàn)鎖提前過期的問題,進(jìn)而導(dǎo)致分布式鎖直接失效
  • 如果鎖的超時時間設(shè)置過長,又會影響到性能

3. 如何實(shí)現(xiàn)鎖的優(yōu)雅續(xù)期

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

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

使用方式舉例:

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

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

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

總的來說就是使用Redisson,它帶有自動的續(xù)期機(jī)制

4. 如何實(shí)現(xiàn)可重入鎖

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

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

到此這篇關(guān)于Java分布式鎖由淺入深介紹的文章就介紹到這了,更多相關(guān)Java分布式鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java編程基礎(chǔ)測試題分享

    Java編程基礎(chǔ)測試題分享

    這篇文章主要介紹了Java編程基礎(chǔ)測試題分享,具有一定參考價值,需要的朋友可以了解下。
    2017-10-10
  • MyBatis?if?test?判斷字符串相等不生效問題

    MyBatis?if?test?判斷字符串相等不生效問題

    這篇文章主要介紹了MyBatis?if?test?判斷字符串相等不生效問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 淺談Spring中HandlerMapping的使用

    淺談Spring中HandlerMapping的使用

    這篇文章主要介紹了淺談Spring中HandlerMapping的使用,Spingmvc中的HandlerMapping負(fù)責(zé)解析請求URL,對應(yīng)到Handler進(jìn)行處理,這里的Handler一般為Controller里的一個方法method,也可以為servlet或者Controller等,需要的朋友可以參考下
    2023-08-08
  • Java substring方法實(shí)現(xiàn)原理解析

    Java substring方法實(shí)現(xiàn)原理解析

    這篇文章主要介紹了Java substring方法實(shí)現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-05-05
  • Java連接服務(wù)器的兩種方式SFTP和FTP

    Java連接服務(wù)器的兩種方式SFTP和FTP

    在項目開發(fā)中,一般文件存儲很少再使用SFTP服務(wù),但是也不排除合作伙伴使用SFTP來存儲項目中的文件或者通過SFTP來實(shí)現(xiàn)文件數(shù)據(jù)的交互,這篇文章主要介紹了Java集成FTP與SFTP連接池
    2023-02-02
  • Spring?Cloud整合XXL-Job的示例代碼

    Spring?Cloud整合XXL-Job的示例代碼

    這篇文章主要介紹了springcloud整合xxl-job的示例代碼,主要分為四個過程,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • 一文詳解如何查看jdk版本及安裝路徑

    一文詳解如何查看jdk版本及安裝路徑

    這篇文章主要給大家介紹了關(guān)于如何查看jdk版本及安裝路徑的相關(guān)資料,JDK是Java語言的軟件開發(fā)工具包,主要用于移動設(shè)備、嵌入式設(shè)備上的java應(yīng)用程序,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10
  • 運(yùn)用springboot搭建并部署web項目的示例

    運(yùn)用springboot搭建并部署web項目的示例

    這篇文章主要介紹了運(yùn)用springboot搭建并部署web項目的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06
  • Servlet實(shí)現(xiàn)文件的上傳與下載

    Servlet實(shí)現(xiàn)文件的上傳與下載

    這篇文章主要為大家詳細(xì)介紹了Servlet實(shí)現(xiàn)文件的上傳與下載,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • Java類鎖、對象鎖、私有鎖沖突測試

    Java類鎖、對象鎖、私有鎖沖突測試

    這篇文章主要介紹了Java類鎖、對象鎖、私有鎖沖突測試,得出結(jié)論是加鎖方法夠成了競爭關(guān)系,同一時刻只能有一個方法能執(zhí)行,需要的朋友可以參考下
    2014-10-10

最新評論