面試官:Redis分散式鎖超時了,任務還沒執行完怎麼辦?

語言: CN / TW / HK

theme: fancy highlight: a11y-dark


圖片

做一個單純的程式汪,分享乾貨,聊聊人生。

微信公眾號:後端架構進階

關注我發現更多的乾貨,微服務、Spring原始碼、JVM、SpringCloud Alibaba、K8S等。

如果你覺得本文對你有幫助,麻煩給我點個贊,感謝支援!

歷史文章彙總:包含Netty、原始碼、併發、JVM等

今天主要分享的是面試中常見的redis的一些面試內容。如果你正好需要剛好可以幫你回顧一下,如果不需要可以收藏起來後面用到的時候翻出來回顧。

一、背景

面試官:你們專案中有使用分散式鎖麼?

我:有使用。

面試官:你們使用分散式鎖主要是為了幹啥?

我:多節點併發訪問同一份資料的時候,防止造成髒資料。

面試官:都有哪些方案實現分散式鎖?你們用的是哪一種?

我:有基於zk的臨時順序節點的方案,有redis的setnx和指定expire超時時間的方案。

面試官:你們是用哪種方案呢?

我:用的是redis的一個封裝元件Redisson。

面試官:你們redis是用的哪種叢集模式?

我:用的是redis的cluster叢集模式。

面試官:Redisson可以配置哪些模式?

我:單節點模式、cluster模式、哨兵模式

面試官:那分散式鎖的鎖超時時間是怎麼配置的?

我:這個超時時間需要根據業務場景進行壓測然後根據壓測結果進行評估,在壓測結果上進行稍微放大1~2倍。

面試官:那假如分散式鎖設定的超時時間是2s,但是2s內還沒執行完成,鎖自動釋放了,這種怎麼處理呢?

我:這個,有點記不清了。

面試官:好的。你們redis cluster叢集模式中,如果主掛了怎麼辦?

我:我們是三主三從的叢集模式,如果半數以上主節點與故障主節點通訊超過,認為當前該主節點掛掉,主下面的從就會變為主。如果主下面沒有從,那麼叢集就會進入fail狀態。從節點就是主節點的備份。

面試官:redis的持久化機制有幾種,分別有什麼優缺點?

我:redis的持久化分為:RDB和AOF,一種是快照,一種是追加。快照的話是一段時間進行資料的備份,追加是隻要有指令執行,就記錄記錄指令資訊。後面可以根據指令進行資料的恢復。

快照模式如果掛了的話很有可能在快照期間資料丟失了,優點是恢復資料比較快,映象的話恢復會比較慢,優點是資料資料存的比較全,配置好持久化策略可以做到資料完全不丟失。

面試官:那你們是怎麼用的?

我:我們是兩種都用,定期備份資料。掛了之後方便快速恢復同時保證了資料的完整性。

真是打破砂鍋問到底啊,兄弟集美們,奪命連環十八問。

不過一碼歸一碼,還是讓我回憶起很多知識。也順帶總結起來,下次遇到這塊問題的時候也不至於啥都說不出來。

接下來,把Redisson在鎖超時後業務還沒執行完成的情況細聊下。

二、Redisson鎖超時看門狗機制

Redisson的宗旨是促進使用者對 Redis 的關注分離(Separation of Concern),從而讓使用者能夠將精力更集中地放在處理業務邏輯上。

先上Github地址,中文文件,賊6。

Redisson中文文件 https://github.com/redisson/redisson/wiki

接下來主要分析:如果鎖已經超時了,但是執行緒還沒執行完任務該如何處理?

可重入鎖(Reentrant Lock)

基於Redis的Redisson分散式可重入鎖RLock Java物件實現了java.util.concurrent.locks.Lock介面。同時還提供了非同步(Async)、反射式(Reactive)和RxJava2標準的介面。

RLock lock = redisson.getLock("anyLock"); //最常見的使用方法 lock.lock();

大家都知道,如果負責儲存這個分散式鎖的Redisson節點宕機以後,而且這個鎖正好處於鎖住的狀態時,這個鎖會出現鎖死的狀態。

為了避免這種情況的發生,Redisson內部提供了一個監控鎖的看門狗,它的作用是在Redisson例項被關閉前,不斷的延長鎖的有效期。

預設情況下,看門狗的檢查鎖的超時時間是30秒鐘,

也可以通過修改Config.lockWatchdogTimeout 來另行指定。

另外Redisson還通過加鎖的方法提供了 leaseTime 的引數來指定加鎖的時間。超過這個時間後鎖便自動解開了。

``` // 加鎖以後10秒鐘自動解鎖 // 無需呼叫unlock方法手動解鎖 lock.lock(10, TimeUnit.SECONDS);

// 嘗試加鎖,最多等待100秒,上鎖以後10秒自動解鎖 boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS); if (res) { try { ... } finally { lock.unlock(); } } ```

拓展:

Redisson同時還為分散式鎖提供了非同步執行的相關方法:

RLock lock = redisson.getLock("anyLock"); lock.lockAsync(); lock.lockAsync(10, TimeUnit.SECONDS); Future<Boolean> res = lock.tryLockAsync(100, 10, TimeUnit.SECONDS);

RLock物件完全符合Java的Lock規範。也就是說只有擁有鎖的程序才能解鎖,其他程序解鎖則會丟擲 IllegalMonitorStateException 錯誤。但是如果遇到需要其他程序也能解鎖的情況,請使用分散式訊號量 Semaphore 物件。

總結

以上就是今日的內容總結和分享,感謝各位大佬的 點贊關注收藏

微信公眾號:後端架構進階

更多文章正在趕來,喜歡記得給我點個 👍 ,感謝支援!

公眾號文章同步更新!關注我,不迷路!