聊聊zookeeper的分布式鎖


  分布式鎖就是多台機器,分布在不同的JVM中,這些不同JVM內的方法需要獲取一個唯一鎖,比如獲取鎖之后要把數據寫入數據庫,保證數據在同一時刻只有一台機器寫入數據庫。

  分布式鎖的實現有多種實現方法,除了今天聊到的ZK實現的分布式鎖還有Redis通過SETNXPX或Lua腳本實現,還可以通過數據庫的鎖實現,但今天咱們主要聊一下ZK的分布式鎖的原理實現。

  zookeeper可以創建兩種節點,一種是永久型的,一種是臨時型還可以是有序的,當機器與zk失去連接的時候臨時節點會自動刪除,這個功能非常強大以至於很多功能都是基於此,比如leader選舉等。現在直接上一張我自己畫的圖:

  

  首先會有一個永久節點\Locks,然后每個客戶端請求的時候會創建一個臨時有序節點,在這時每個都是有序的,最小的節點就意味着獲取了鎖。

       在此圖上顯然ClientC獲取了鎖,其他的鎖獲取的節點不是最小的,但是他們之前會有一個鏈接,就是lock_00000001在雖然沒有獲取鎖,但是會需要監聽lock_00000000的,因為如果監聽所有節點的話會浪費很多的資源。相應的大的節點都會watch比自己小的節點,當比自己節點小的節點釋放之后然后就可以繼續處理了。

  我們看看Curator很好的幫我們實現了這樣的功能,所有大家可以直接拿過來用:  

        InterProcessMutex lock = new InterProcessMutex(client, lockPath);
        try {
            lock.acquire(seconds, TimeUnit.SECONDS);
            //do something
        } catch (Exception e) {
            logger.error("error", e);
        } finally {
            lock.release();
        }

  很多東西都為我們封裝好了,如果用原生zookeepr API需要寫太多的行,並且需要考慮的點非常的多。我在網上也找了一個例子,自己改了一把,然后跑了沒有什么問題, 因為不是自己寫的,所有不貼出來了,有需要了自行下載: https://github.com/stonehqs/Demo/blob/master/ZookeeperLock.java

  但是在這里邊我能想到的還有一場景需要大家一起思考一下:

  1. 如果ZK集群出問題了,如何處理?

  2. 如果方法調用的太頻繁,這樣會出現連接ZK被拒絕,比如一個應用連接數超過60個。

  大家如果有更好的方案,可以給我留言討論。

 

  我能想到的第1點就是采用多個集群,比如兩個集群,在寫入數據的時候同時寫入到兩個集群中(保證數據一致),如果有一個群集中超過一半不能使用的時候,那么整個集群不能用了,這時可以切換到另一個群集,保證訪問的高可用。 

  關於第2點,每個連接ZK群集的IP會被記錄下來,這樣一個IP連接ZK集群的最大默認數量60個,如果超過60個的話會被拒絕連接,防止DDOS攻擊。所以在每個應用的方法調用的時候需要加入synchronized關鍵字,這樣每個應用在同一時刻有一個線程在進行處理,其他的線程可以等待或者直接去做別的處理。還有另一個方案就是調整這個數變大,這樣也可以解決一下,但是如果調整的話還需要多做一些測試,保證這個數字是最佳的。

  好了,有問題的可以給我留言。下期再見。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM