聊聊zookeeper的分佈式鎖

  分佈式鎖就是多臺機器,分佈在不一樣的JVM中,這些不一樣JVM內的方法須要獲取一個惟一鎖,好比獲取鎖以後要把數據寫入數據庫,保證數據在同一時刻只有一臺機器寫入數據庫。java

  分佈式鎖的實現有多種實現方法,除了今天聊到的ZK實現的分佈式鎖還有Redis經過SETNXPX或Lua腳本實現,還能夠經過數據庫的鎖實現,但今天我們主要聊一下ZK的分佈式鎖的原理實現。git

  zookeeper能夠建立兩種節點,一種是永久型的,一種是臨時型還能夠是有序的,當機器與zk失去鏈接的時候臨時節點會自動刪除,這個功能很是強大以致於不少功能都是基於此,好比leader選舉等。如今直接上一張我本身畫的圖:github

  

  首先會有一個永久節點\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.javaui

  可是在這裏邊我能想到的還有一場景須要你們一塊兒思考一下:spa

  1. 若是ZK集羣出問題了,如何處理?線程

  2. 若是方法調用的太頻繁,這樣會出現鏈接ZK被拒絕,好比一個應用鏈接數超過60個。code

  你們若是有更好的方案,能夠給我留言討論。

 

  我能想到的第1點就是採用多個集羣,好比兩個集羣,在寫入數據的時候同時寫入到兩個集羣中(保證數據一致),若是有一個羣集中超過一半不能使用的時候,那麼整個集羣不能用了,這時能夠切換到另外一個羣集,保證訪問的高可用。 

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

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

相關文章
相關標籤/搜索