天天看點

Zookeeper深度解析(概念、原理機制、應用場景)一、什麼是Zookeeper?二、Zookeeper設計目的三、Zookeeper的安裝三、Zookeeper的檔案系統四、zookeeper的通知(Watch)機制五、zookeeper應用場景六、zookeeper叢集七、zookeeper配置詳解

一、什麼是Zookeeper?

       Zookeeper是一個高效的分布式一緻性協調服務,可以提供配置資訊管理、命名、分布式同步、叢集管理、資料庫切換等服務。它不适合用來存儲大量資訊,可以用來存儲一些配置、釋出與訂閱等少量資訊。(Zookeeper 作為 Hadoop 項目中的一個子項目,是 Hadoop 叢集管理的一個必不可少的子產品,它主要用來控制叢集中的資料,如它管理 Hadoop 叢集中的 NameNode,還有 Hbase 中 Master Election、Server 之間狀态同步等。)

二、Zookeeper設計目的

  1. 最終一緻性:client不論連接配接到哪個Server,展示給它都是同一個視圖,這是zookeeper最重要的性能。
  2. 可靠性:具有簡單、健壯、良好的性能,如果消息m被到一台伺服器接受,那麼它将被所有的伺服器接受。
  3. 實時性:Zookeeper保證用戶端将在一個時間間隔範圍内獲得伺服器的更新資訊,或者伺服器失效的資訊。但由于網絡延時等原因,Zookeeper不能保證兩個用戶端能同時得到剛更新的資料,如果需要最新資料,應該在讀資料之前調用sync()接口。
  4. 等待無關(wait-free):慢的或者失效的client不得幹預快速的client的請求,使得每個client都能有效的等待。
  5. 原子性:更新隻能成功或者失敗,沒有中間狀态。
  6. 順序性:包括全局有序和偏序兩種:全局有序是指如果在一台伺服器上消息a在消息b前釋出,則在所有Server上消息a都将在消息b前被釋出;偏序是指如果一個消息b在消息a後被同一個發送者釋出,a必将排在b前面。

三、Zookeeper的安裝

  1. 前置環境:已安裝好jdk
  2. 下載下傳zookeeper的安裝包:官網下載下傳,下載下傳和解壓到/usr/local中
  3. 建立資料、日志檔案夾:
    mkdir  /usr/local/zookeeper/data
    mkdir  /usr/local/zookeeper/log
               
  4. 設定核心配置檔案:
    #打開核心配置
    mv /usr/local/zookeeper/conf/zoo_sample.cfg  /usr/local/zookeeper/conf/zoo.cfg
    
    #設定核心配置檔案
    vim /usr/local/zookeeper/conf/zoo.cfg
    
    #填入如下配置
    dataDir=/usr/local/zookeeper/data
    dataLogDir=/usr/local/zookeeper/log
               
  5. 啟動zookeeper
    cd /usr/local/zookeeper/bin
    
    #啟動zookeeper
    ./zkServer.sh start
               

三、Zookeeper的檔案系統

檔案系統的資料結構

zookeeper是用一個樹形結構來進行資料存儲管理的。它不适合用來存儲大量資訊,可以用來存儲一些配置、釋出與訂閱等少量資訊。如下圖所示:

Zookeeper深度解析(概念、原理機制、應用場景)一、什麼是Zookeeper?二、Zookeeper設計目的三、Zookeeper的安裝三、Zookeeper的檔案系統四、zookeeper的通知(Watch)機制五、zookeeper應用場景六、zookeeper叢集七、zookeeper配置詳解

檔案系統的節點(znode)

什麼是znode?

       每個子目錄項如 NameService 都被稱作為znode,和檔案系統一樣,我們能夠自由的增加、删除znode,在一個znode下增加、删除子znode,每個znode都是可以存儲資料的。

znode的分類

  • persistent-持久化目錄節點:持久節點就是節點被建立後會一直存在伺服器,直到删除操作主動清除,這種節點也是最常見的類型。
  • persistent_sequential-持久化順序編号目錄節點:持久順序節點就是有順序的持久節點,節點特性和持久節點是一樣的,隻是額外特性表現在順序上。順序特性實質是在建立節點的時候,會在節點名後面加上一個數字字尾,來表示其順序。
  • ephemeral-臨時目錄節點:臨時節點就是會被自動清理掉的節點,它的生命周期和用戶端會話綁在一起,用戶端會話結束,節點會被删除掉。與持久性節點不同的是,臨時節點不能建立子節點。
  • ephemeral_sequential-臨時順序編号目錄節點:臨時順序節點就是有順序的臨時節點,和持久順序節點相同,在其建立的時候會在名字後面加上數字字尾。

檔案系統的操作指令

運作zkCli.sh –server <ip:port>進入指令行工具,注意連接配接資訊應該為zoo.cfg中配置的主機名或者ip

        ls path指令

            指令來檢視目前znode下所包含的子節點

        create [-s] [-e] path data acl 指令

            建立節點指令,[-s] 順序節點,[-e] 臨時性節點,path 路徑,data 資料内容,acl 權限

            例如:create -s -e /newnode1 mydata

        get path 指令

            擷取znode 資訊

            例如:get /app1

整個 ZNode 節點内容包括兩部分:節點資料内容和節點狀态資訊。
cZxid 就是 Create ZXID,表示節點被建立時的事務 ID。
mZxid 就是 Modified ZXID,表示節點最後一次被修改時的事務 ID。
ctime 就是 Create Time,表示節點建立時間。
mtime 就是 Modified Time,表示節點最後一次被修改的時間。
pZxid 表示該節點的子節點清單最後一次被修改時的事務 ID。隻有子節點清單變更才會更新 pZxid,子節點内容變更不會更新。
cversion 表示子節點的版本号。
dataVersion 表示内容版本号。
dataLength 表示資料長度。
numChildren 表示子節點數。
ephemeralOwner 表示建立該臨時節點時的會話 sessionID,如果是持久性節點那麼值為 0。
           

      set path data [version] 指令

            修改節點資料。path 是路徑 data 是資料内容 [version] 是版本号,我們可以通過 set /app1 newapp1 來更新節點 /app1的内容,也可以自己設定版本号

            例如: set /newnode1 updatedata

     delete path [version] 指令

            删除節點。

Java程式調用zookeeper的API操作節點

springboot整合zookeeper部落格(轉載連結)

zookeeper簡便工具ZKclient的使用(轉載連結)

引入依賴

<dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.10</version>
        </dependency>
           

連接配接zookeeper

String hostPort = "192.168.137.88:2181";
  String rootPath = "/";
  ZooKeeper zooKeeper = new ZooKeeper(hostPort, 1000, null);
           

建立節點

// 建立一個目錄節點
zookeeper.create("/mynode", "world".getBytes(), Ids.OPEN_ACL_UNSAFE,
   CreateMode.PERSISTENT); 
           

擷取節點狀态資訊

Stat falg = zooKeeper.exists("/mynode", false);
           

擷取節點資料内容

byte[] data2 = zooKeeper.getData("/mynode", false, null);
           

修改節點資料

zooKeeper.setData("/mynode", "hello world!!!".getBytes(),  -1);
           

删除節點

zooKeeper.delete("/mynode", -1);
           

關閉連接配接

zooKeeper.close();
           

四、zookeeper的通知(Watch)機制

什麼是zookeeper的通知機制?

       Znode發生變化(Znode本身的增加,删除,修改,以及子Znode的變化)可以通過Watch機制通知到用戶端。那麼要實作Watch,就必須實作org.apache.zookeeper.Watcher接口,并且将實作類的對象傳入到可以Watch的方法中。Zookeeper中所有讀操作(getData(),getChildren(),exists())都可以設定Watch選項。Watch事件具有one-time trigger(一次性觸發)的特性,如果Watch監視的Znode有變化,那麼就會通知設定該Watch的用戶端。

watch類型

       資料watch(data  watches):getData和exists負責設定資料watch

       孩子watch(child watches):getChildren負責設定孩子watch

注意:

  • exists操作上的watch,在被監視的Znode建立、删除或資料更新時被觸發。
  • getData操作上的watch,在被監視的Znode删除或資料更新時被觸發。在被建立時不能被觸發,因為隻有Znode一定存在,getData操作才會成功。
  • getChildren操作上的watch,在被監視的Znode的子節點建立或删除,或是這個Znode自身被删除時被觸發。可以通過檢視watch事件類型來區分是Znode,還是他的子節點被删除:NodeDelete表示Znode被删除,NodeDeletedChanged表示子節點被删除。

Java API設定Watch機制

        建立自定義Watch監聽類

/**
 * 自定義watch
 */
public class MyWatch implements Watcher {

    public void process(WatchedEvent watchedEvent) {
        System.out.println("監控的節點:" + watchedEvent.getPath());
        System.out.println("監控的類型:" + watchedEvent.getType());
    }
}
           

        設定Watch監聽

ZooKeeper zooKeeper = new ZooKeeper(hostPort, 1000, null);
        zooKeeper.getChildren(rootPath, new MyWatch());
           

    事件類型

        None:在用戶端與Zookeeper叢集中的伺服器斷開連接配接的時候,用戶端會收到這個事件

        NodeCreated:Znode建立事件

        NodeDeleted:Znode删除事件

        NodeDataChanged:Znode資料内容更新事件。其實本質上該事件隻關注dataVersion版本号,但是隻要調用了更新接口      dataVersion就會有變更

        NodeChildrenChanged:Znode子節點改變事件,隻關注子節點的個數變更,子節點内容有變更是不會通知的

五、zookeeper應用場景

1、配置檔案管理

(1) 什麼是配置檔案管理?

            程式通常會需要進行一些配置檔案進行配置的管理。但是如果對于分布式項目來說,可能會部署在不同的伺服器上,這樣每台服務都會有自己的一套配置,如果需要對某些配置進行調整,則需要逐一的對各個伺服器進行修改。zookeeper能夠實作統一的配置檔案管理。

(2) 如何管理配置檔案?

            将需要統一管理的配置全部放到zookeeper上去,儲存在 Zookeeper 的某個目錄節點中,然後所有相關應用程式對這個目錄節點進行監聽,一旦配置資訊發生變化,每個應用程式就會收到 Zookeeper 的通知,然後從 Zookeeper 擷取新的配置資訊應用到系統中就好

Zookeeper深度解析(概念、原理機制、應用場景)一、什麼是Zookeeper?二、Zookeeper設計目的三、Zookeeper的安裝三、Zookeeper的檔案系統四、zookeeper的通知(Watch)機制五、zookeeper應用場景六、zookeeper叢集七、zookeeper配置詳解

2、叢集管理

(1) 什麼是叢集管理?

            所謂叢集管理無在乎兩點:是否有機器退出和加入、選舉master。

(2) 如何管理叢集?

            對于第一點,所有機器約定在父目錄GroupMembers下建立臨時目錄節點,然後監聽父目錄節點的子節點變化消息。一旦有機器挂掉,該機器與 zookeeper的連接配接斷開,其所建立的臨時目錄節點被删除,所有其他機器都收到通知:某個兄弟目錄被删除。新機器加入也是類似,所有機器收到通知:新兄弟目錄加入,highcount又有了。

            對于第二點,我們稍微改變一下,所有機器建立臨時順序編号目錄節點,每次選取編号最小的機器作為master就好。

Zookeeper深度解析(概念、原理機制、應用場景)一、什麼是Zookeeper?二、Zookeeper設計目的三、Zookeeper的安裝三、Zookeeper的檔案系統四、zookeeper的通知(Watch)機制五、zookeeper應用場景六、zookeeper叢集七、zookeeper配置詳解

3、分布式鎖

(1) 分布式鎖的實作方式

            保持獨占

                我們将zookeeper上的一個znode看作是一把鎖,通過createznode的方式來實作。所有用戶端都去建立 /distribute_lock 節點,最終成功建立的那個用戶端也即擁有了這把鎖。用完删除掉自己建立的distribute_lock 節點就釋放出鎖

            控制時序

                /distribute_lock 已經預先存在,所有用戶端在它下面建立臨時順序編号目錄節點,和選master一樣,編号最小的獲得鎖,用完删除,依次友善

Zookeeper深度解析(概念、原理機制、應用場景)一、什麼是Zookeeper?二、Zookeeper設計目的三、Zookeeper的安裝三、Zookeeper的檔案系統四、zookeeper的通知(Watch)機制五、zookeeper應用場景六、zookeeper叢集七、zookeeper配置詳解

4、命名服務

       在日常開發中,我們會遇到這樣的場景:服務A需要通路服務B,但是服務B還在開發過程中(未完成),那麼服務A(此時已完成)就不知道如何擷取服務B的通路路徑了,使用zookeeper的服務就可以簡單解決:服務B部署成功後,可以先到zookeeper注冊服務(即在zookeeper添加節點/service/B和節點資料)。服務A開發結束後,部署到伺服器,然後服務A監控zookeeper服務節點/service/B,如果發現節點資料了,那麼服務A就可以通路服務B了。

六、zookeeper叢集

1、zookeeper的叢集搭建

僞叢集模式

       什麼是僞叢集模式?

              所謂僞叢集, 是指在單台機器中啟動多個zookeeper程序, 并組成一個叢集. 

        步驟:

  • 将單機安裝的zookeeper檔案夾複制2份
  • 在每份zookeeper檔案夾中的data目錄下建立一個myid檔案,并且寫入一個編号(每個zookeeper服務的編号必須不同,1、2、3)
  • 配置核心配置檔案
  • 依次啟動每個zookeeper服務
  • 檢視每個zookeeper服務的狀态

叢集模式

       叢集模式的配置和僞叢集基本一緻.由于叢集模式下, 各server部署在不同的機器上, 是以各server的conf/zoo.cfg檔案可以完全一樣.

zookeeper叢集的“過半數存活”原則

       什麼是“過半數存活”原則?

            “半數存活”原則,即叢集中存活的伺服器數量必須為總伺服器數量的一半以上。

        注意:

            由于zookeeper過半數存活機制,是以在叢集搭建的時候,我們通常都是搭建奇數台伺服器。因為2N+1台伺服器和2N+2  台伺服器的容災能力都是一樣的,都是允許挂掉N台伺服器(3台允許挂1台,4台也允許挂1台,依次類推)。是以基于成本考慮,2N+1台的選擇方案更優。

zookeeper叢集的角色

Zookeeper深度解析(概念、原理機制、應用場景)一、什麼是Zookeeper?二、Zookeeper設計目的三、Zookeeper的安裝三、Zookeeper的檔案系統四、zookeeper的通知(Watch)機制五、zookeeper應用場景六、zookeeper叢集七、zookeeper配置詳解

zookeeper叢集的核心

  • ZAB協定

    ZooKeeper作為高可用的一緻性協調架構,自然的ZooKeeper也有着一緻性算法的實作,ZooKeeper使用的是ZAB協定作為資料一緻性的算法,ZAB(ZooKeeper Atomic Broadcast )全稱為:原子消息廣播協定

  • ZAB協定的基礎

    Leader選舉:

    在ZooKeeper中所有的事務請求都由一個主伺服器也就是Leader來處理,其他伺服器為Follower,Leader将用戶端的事務請求轉換為事務Proposal,并且将Proposal分發給叢集中其他所有的Follower,然後Leader等待Follwer回報,當有過半數(>=N/2+1)的Follower回報資訊後,Leader将再次向叢集内Follower廣播Commit資訊,Commit為将之前的Proposal送出

  • ZAB協定的狀态

    每個ZAB協定中,每個節點都屬于以下三種中的一種

    Looking:系統剛啟動時或者Leader崩潰後正處于選舉狀态

    Following:Follower節點所處的狀态,Follower與Leader處于資料同步階段

    Leading:Leader所處狀态,目前叢集中有一個Leader為主程序

    Zookeeper深度解析(概念、原理機制、應用場景)一、什麼是Zookeeper?二、Zookeeper設計目的三、Zookeeper的安裝三、Zookeeper的檔案系統四、zookeeper的通知(Watch)機制五、zookeeper應用場景六、zookeeper叢集七、zookeeper配置詳解

七、zookeeper配置詳解

tickTime:心跳間隔時間。zookeeper中使用的基本時間機關, 毫秒值。

dataDir:資料目錄。修改為zookeeper安裝目錄下的data目錄,data目錄自己建立,當然也可以指定為别的目錄。

clientPort:用戶端連接配接端口。用戶端通過該端口連接配接Zookeeper。

initLimit:Follower初始化連接配接時和Leader連接配接的逾時時間。zookeeper叢集中的包含多台server,其中一台為leader,叢集中其    餘的server為follower。initLimit參數配置初始化連接配接時,follower和leader之間的最長心跳時間。此時該參數設定為5,說明時間限制為5倍tickTime,即5*2000=10000ms=10s

syncLimit:該參數配置leader和follower之間發送消息,請求和應答的最大時間長度。此時該參數設定為2,說明時間限制為2倍tickTime,即4000ms

叢集配置:

server.serverid=serverhost:leader_listent_port:quorum_port

serverid:是目前zookeeper伺服器的id(myid檔案中寫的編号)。

leader_listen_port:通常叫做原子廣播端口,是該伺服器一旦成為leader之後需要監聽的端口,用于接收來自follower的請求。

quorum_port:通常叫做選舉端口,是叢集中的每一個伺服器在最開始選舉leader時監聽的端口,用于伺服器互相之間通信選舉leader。

繼續閱讀