大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節點LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 學習攻略 職業指南 還是一樣高頻出現的Java分布式鎖面試題

還是一樣高頻出現的Java分布式鎖面試題

更新時間:2023-02-15 16:00:07 來源:動力節點 瀏覽3054次

1.為什么需要分布式鎖?

public synchronized void test() {
    System.out.println("獲取到鎖");
}
public void test2() {
     synchronized (Test.class) {
          System.out.println("獲取到鎖");
     }
}

假設我們把上述代碼部署到多臺服務器上,這個互斥鎖還能生效嗎?答案是否定的,這時分布式鎖應運而生。

2.Redis分布式鎖?

接下來我給大家講解完整的演變過程,讓大家更深刻的理解分布式鎖。

java分布式鎖面試題

Redis setnx

線程1申請加鎖,這時沒有人持有鎖,加鎖成功:

127.0.0.1:6379> setnx lock 1
(integer) 1

線程2申請加鎖,此時發現有人持有鎖未釋放,加鎖失?。?/p>

127.0.0.1:6379> setnx lock 1
(integer) 0

線程1執行完成業務邏輯后,執行DEL命令釋放鎖:

127.0.0.1:6379> del lock
(integer) 1

存在問題:

①假設線程1執行到一半,系統掛了,這時鎖還沒釋放,就會造成死鎖。

②如果Redis加鎖后,Master還沒同步給Slave就掛了,會導致有兩個客戶端獲取到鎖

解決方案:setnx expire

Redis setnx expire

為了解決上述死鎖問題,我們在setnx后,給這個key加上失效時間。

此時線程1加鎖的代碼改成:

127.0.0.1:6379> setnx lock 1 ## 加鎖
(integer) 1
127.0.0.1:6379> expire lock 3 ## 設置 key 3秒失效
(integer) 1

存在問題:

①假設setnx lock 1執行成功了,但是expire lock 3執行失敗了,還是會存在死鎖問題,這兩個命令需要保證原子性。

②失效時間是我們寫死的,不能自動續約,如果業務執行時間超過失效時間,會出現線程1還在執行,線程2就加鎖成功了,并有沒達到互斥效果。

③如果Redis加鎖后,Master還沒同步給Slave就掛了,會導致有兩個客戶端獲取到鎖

解決方案:RedissonLock

RedissonLock

上述兩個問題,RedissonLock都解決了,我通過源碼給大家剖析,看RedissonLock是如何解決的,基礎好的小伙伴可以好好讀讀源碼,其實RedissonLock源碼也不難。

我先寫結論,基礎較弱的小伙伴,只要記得結論就行:

java分布式鎖面試題

①RedisssonLock底層使用的是lua腳本執行的redis指令,lua腳本可以保證加鎖和失效指令的原子性。

②RedisssonLock底層有個看門狗機制,加鎖成功后,會開啟一個定時調度任務,每隔10秒去檢查鎖是否釋放,如果沒有釋放,把失效時間刷新成30秒。這樣鎖就可以一直續期,不會釋放。

我看的是3.12.5版本源碼,不同版本實現上可能存在一些差異。

應用程序加鎖代碼:

RLock lock = redissonLock.getLock("anyLock");
lock.lock();

RedissonLock加鎖核心代碼:

java分布式鎖面試題

RedissonLock獲取鎖核心代碼:

java分布式鎖面試題

底層加鎖邏輯:

java分布式鎖面試題

KEYS[1] = anyLock,鎖的名稱。

ARGV[1] = 30000,失效時間,通過lockWatchdogTimeout配置。

ARGV[2] = c1b51ddb-1505-436c-a308-b3b75b4bd407:1,他是ConnectionManager的ID,我們可以簡單的把它理解為一個客戶端的一個線程對應的唯一標志性。

RedissonLock解鎖核心代碼:

java分布式鎖面試題

存在問題:如果redis是單節點,存在單節點故障問題;如果做主從架構,Redis加鎖后,Master還沒同步給Slave就掛了,會導致有兩個客戶端獲取到鎖

有小伙伴問我,如果這里我用集群會存在這個問題嗎?集群的本質是分片,這個key最終還是會落到某個具體的節點,這個節點要么是單獨存在,要么是主從架構,所以還是會存在上述問題。

解決方案:RedLock

補充:雖然RedLock可以解決上述問題,但是在生產環境中我們很少使用,因為它部署成本很高,相比RedissonLock性能也略微有所下降?。

如果業務能接受極端情況下存在互斥失敗問題,并且對性能要求比較高,我們會選擇RedissonLock,并做好響應?的兜底方案。

如果業務對數據要求絕對正確,?我們會采用Zookeeper來做分布式鎖。?

Redlock

我們假設有5個完全相互獨立的Redis Master單機節點,所以我們需要在5臺機器上面運行這些實例,如下圖所示(請注意這張圖中5個Master節點完全相互獨立)

為了取到鎖,客戶端應該執行以下操作:

java分布式鎖面試題

①獲取當前Unix時間,以毫秒為單位。

②依次嘗試從N個Master實例使用相同的key和隨機值獲取鎖(假設這個key是LOCK_KEY)。當向Redis設置鎖時,客戶端應該設置一個網絡連接和響應超時時間,這個超時時間應該小于鎖的失效時間。例如你的鎖自動失效時間為10秒,則超時時間應該在5-50毫秒之間。這樣可以避免服務器端Redis已經掛掉的情況下,客戶端還在死死地等待響應結果。如果服務器端沒有在規定時間內響應,客戶端應該盡快嘗試另外一個Redis實例。

③客戶端使用當前時間減去開始獲取鎖時間(步驟1記錄的時間)就得到獲取鎖使用的時間。當且僅當從大多數的Redis節點都取到鎖,并且使用的時間小于鎖失效時間時,鎖才算獲取成功。

④如果取到了鎖,key的真正有效時間等于有效時間減去獲取鎖所使用的時間(步驟3計算的結果)。

⑤如果因為某些原因,獲取鎖失敗(沒有在至少N/2+1個Redis實例取到鎖或者取鎖時間已經超過了有效時間),客戶端應該在所有的Redis實例上進行解鎖(即便某些Redis實例根本就沒有加鎖成功)。

缺點:像我們系統,并發量比較大,生產環境必須要做分片才能扛住并發,像上述方案,我們需要準備5個Redis集群,這種機器成本是非常高的。

以上就是“還是一樣高頻出現的Java分布式鎖面試題”,你能回答上來嗎?如果想要了解更多的Java面試題相關內容,可以關注動力節點Java官網。

提交申請后,顧問老師會電話與您溝通安排學習

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 二性视频 | 中文字幕在线精品视频万部 | 欧美 日产 国产精品 | 国产精品久久久久精 | 国产剧情一区二区三区 | 国产三级做爰高清视频a | 国产高清美女一级a毛片久久w | 国产精品久线观看视频 | 国产精品99爱免费视频 | 激情 婷婷 | 久久女同互慰一区二区三区 | 在线a毛片免费视频观看 | 欧美丰满大乳大屁股毛片 | 亚洲精品在线视频观看 | 欧美精品成人久久网站 | 一区二区国产一区二区a4yy | 欧美特黄一级大黄录像 | 亚洲人成影院午夜网站 | 奇米影视一区二区三区 | 久久99精品久久久久久国产越南 | 久草观看视频 | 成人精品一区二区三区 | 99热久久这里就有精品 | 狠狠色噜噜噜噜狠狠狠狠狠狠奇米 | 天天曰天天| 国产精品社区 | 欧美午夜在线观看理论片 | 99精品在线观看 | 99热精品久久 | 欧美影院一区二区三区 | 久久www免费人成看国产片 | 香蕉网久久 | 成人啪啪97丁香 | 亚洲视频日韩视频 | 快射视频网| 亚洲日韩在线视频 | 高清在线亚洲精品国产二区 | 亚洲 欧美 另类 天天更新影院 | 俄罗斯一级在线播放 | 99亚洲 | 欧美不卡视频在线 |