【面試普通人VS高手系列】請說一下你對分散式鎖的理解,以及分散式鎖的實現

跟著Mic學架構發表於2022-04-27

一個工作了7年的Java程式設計師,私信我關於分散式鎖的問題。

一上來就兩個靈魂拷問:

  • Redis鎖超時怎麼辦?
  • Redis主從切換導致鎖失效怎麼辦?

我說,彆著急,這些都是小問題。

那麼,關於“分散式鎖的理解和實現”這個問題,我們看看普通人高手的回答。

普通人:

嗯,分散式鎖,就是可以用來實現鎖的分佈性,嗯…

就是可以解決跨程式的應用對於共享資源訪問的衝突問題。

可以用Redis來實現分散式鎖。

高手:

分散式鎖,是一種跨程式的跨機器節點的互斥鎖,它可以用來保證多機器節點對於共享資源訪問的排他性。

image-20220327141240705

我覺得分散式鎖和執行緒鎖本質上是一樣的,執行緒鎖的生命週期是單程式多執行緒,分散式鎖的宣告週期是多程式多機器節點。

在本質上,他們都需要滿足鎖的幾個重要特性:

  • 排他性,也就是說,同一時刻只能有一個節點去訪問共享資源。
  • 可重入性,允許一個已經獲得鎖的程式,在沒有釋放鎖之前再次重新獲得鎖。
  • 鎖的獲取、釋放的方法
  • 鎖的失效機制,避免死鎖的問題

所以,我認為,只要能夠滿足這些特性的技術元件都能夠實現分散式鎖。

  1. 關係型資料庫,可以使用唯一約束來實現鎖的排他性,

    如果要針對某個方法加鎖,就可以建立一個表包含方法名稱欄位,

    並且把方法名設定成唯一的約束。

    那搶佔鎖的邏輯就是:往表裡面插入一條資料,如果已經有其他的執行緒獲得了某個方法的鎖,那這個時候插入資料會失敗,從而保證了互斥性。

    這種方式雖然簡單啊,但是要實現比較完整的分散式鎖,還需要考慮重入性、鎖失效機制、沒搶佔到鎖的執行緒要實現阻塞等,就會比較麻煩。

  2. Redis,它裡面提供了SETNX命令可以實現鎖的排他性,當key不存在就返回1,存在就返回0。然後還可以用expire命令設定鎖的失效時間,從而避免死鎖問題。

    當然有可能存在鎖過期了,但是業務邏輯還沒執行完的情況。 所以這種情況,可以寫一個定時任務對指定的key進行續期。

    Redisson這個開源元件,就提供了分散式鎖的封裝實現,並且也內建了一個Watch Dog機制來對key做續期。

    我認為Redis裡面這種分散式鎖設計已經能夠解決99%的問題了,當然如果在Redis搭建了高可用叢集的情況下出現主從切換導致key失效,這個問題也有可能造成

    多個執行緒搶佔到同一個鎖資源的情況,所以Redis官方也提供了一個RedLock的解決辦法,但是實現會相對複雜一些。

  3. 在我看來,分散式鎖應該是一個CP模型,而Redis是一個AP模型,所以在叢集架構下由於資料的一致性問題導致極端情況下出現多個執行緒搶佔到鎖的情況很難避免。

    那麼基於CP模型又能實現分散式鎖特性的元件,我認為可以選擇Zookeeper或者etcd,

    • 在資料一致性方面,zookeeper用到了zab協議來保證資料的一致性,etcd用到了raft演算法來保證資料一致性。
    • 在鎖的互斥方面,zookeeper可以基於有序節點再結合Watch機制實現互斥和喚醒,etcd可以基於Prefix機制和Watch實現互斥和喚醒。

以上就是我對於分散式鎖的理解!

總結

我認為,回答這個問題的核心本質,還是在技術底層深度理解的基礎上的思考。

可以從高手的回答中明顯感受到,對於排它鎖底層邏輯的理解是很深刻的,同時再技術的廣度上也是有足夠的積累。

所以在回答的時候,面試官可以去抓到求職者在回答這個問題的時候的技術關鍵點和技術思維。

我認為,當具備體系化的技術能力的時候,是很容易應對各種面試官的各種刁難的。

好的,本期的普通人VS高手面試系列就到這裡結束了,喜歡的朋友記得點贊和收藏。

另外,有任何技術上的問題,職業發展有關的問題,都可以私信我,我會在第一時間回覆。

file

版權宣告:本部落格所有文章除特別宣告外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Mic帶你學架構
如果本篇文章對您有幫助,還請幫忙點個關注和贊,您的堅持是我不斷創作的動力。歡迎關注「跟著Mic學架構」公眾號公眾號獲取更多技術乾貨!

相關文章