Zookeeper快速入門

codeing_docs發表於2019-01-16

Zookeeper 概述

ZooKeeper是一種分散式協調服務,用於管理大型主機。在分散式環境中協調和管理服務是一個複雜的過程。ZooKeeper通過其簡單的架構和API解決了這個問題。ZooKeeper允許開發人員專注於核心應用程式邏輯,而不必擔心應用程式的分散式特性。

分散式應用的優點

  • 可靠性 - 單個或幾個系統的故障不會使整個系統出現故障。
  • 可擴充套件性 - 可以在需要時增加效能,通過新增更多機器,在應用程式配置中進行微小的更改,而不會有停機時間。
  • 透明性 - 隱藏系統的複雜性,並將其顯示為單個實體/應用程式。

分散式應用的挑戰

  • 競爭條件 - 兩個或多個機器嘗試執行特定任務,實際上只需在任意給定時間由單個機器完成。例如,共享資源只能在任意給定時間由單個機器修改。
  • 死鎖 - 兩個或多個操作等待彼此無限期完成。
  • 不一致 - 資料的部分失敗。

什麼是Apache ZooKeeper?

Apache ZooKeeper是由叢集(節點組)使用的一種服務,用於在自身之間協調,並通過穩健的同步技術維護共享資料。ZooKeeper本身是一個分散式應用程式,為寫入分散式應用程式提供服務。

ZooKeeper提供的常見服務如下 :

  • 命名服務 - 按名稱標識叢集中的節點。它類似於DNS,但僅對於節點。
  • 配置管理 - 加入節點的最近的和最新的系統配置資訊。
  • 叢集管理 - 實時地在叢集和節點狀態中加入/離開節點。
  • 選舉演算法 - 選舉一個節點作為協調目的的leader。
  • 鎖定和同步服務 - 在修改資料的同時鎖定資料。此機制可幫助你在連線其他分散式應用程式(如Apache HBase)時進行自動故障恢復。
  • 高度可靠的資料登錄檔 - 即使在一個或幾個節點關閉時也可以獲得資料。

ZooKeeper的好處

  • 簡單的分散式協調過程
  • 同步 - 伺服器程式之間的相互排斥和協作。此過程有助於Apache HBase進行配置管理。
  • 有序的訊息
  • 序列化 - 根據特定規則對資料進行編碼。確保應用程式執行一致。這種方法可以在MapReduce中用來協調佇列以執行執行的執行緒。
  • 可靠性
  • 原子性 - 資料轉移完全成功或完全失敗,但沒有事務是部分的。

ZooKeeper的架構

輸入圖片說明
螢幕截圖.png

Client(客戶端)

  • 客戶端,我們的分散式應用叢集中的一個節點,從伺服器訪問資訊。對於特定的時間間隔,每個客戶端向伺服器傳送訊息以使伺服器知道客戶端是活躍的。類似地,當客戶端連線時,伺服器傳送確認碼。如果連線的伺服器沒有響應,客戶端會自動將訊息重定向到另一個伺服器。

Server(伺服器)

  • 伺服器,我們的ZooKeeper總體中的一個節點,為客戶端提供所有的服務。向客戶端傳送確認碼以告知伺服器是活躍的。

Ensemble

  • ZooKeeper伺服器組。形成ensemble所需的最小節點數為3。

Leader:

  • 伺服器節點,如果任何連線的節點失敗,則執行自動恢復。Leader在服務啟動時被選舉。

Follower

  • 跟隨leader指令的伺服器節點。

層次名稱空間

ZooKeeper節點稱為 znode 。每個znode由一個名稱標識,並用路徑(/)序列分隔。

輸入圖片說明
螢幕截圖.png

  • config 名稱空間用於集中式配置管理,workers 名稱空間用於命名。
  • 在 config 名稱空間下,每個znode最多可儲存1MB的資料。這與UNIX檔案系統相類似,除了父znode也可以儲存資料。這種結構的主要目的是儲存同步資料並描述znode的後設資料。此結構稱為 ZooKeeper資料模型。
  • ZooKeeper資料模型中的每個znode都維護著一個 stat 結構。一個stat僅提供一個znode的後設資料。它由版本號,操作控制列表(ACL),時間戳和資料長度組成。
  1. 版本號 - 每個znode都有版本號,這意味著每當與znode相關聯的資料發生變化時,其對應的版本號也會增加。當多個zookeeper客戶端嘗試在同一znode上執行操作時,版本號的使用就很重要。
  2. 操作控制列表(ACL) - ACL基本上是訪問znode的認證機制。它管理所有znode讀取和寫入操作。
  3. 時間戳 - 時間戳表示建立和修改znode所經過的時間。它通常以毫秒為單位。ZooKeeper從“事務ID"(zxid)標識znode的每個更改。Zxid是唯一的,並且為每個事務保留時間,以便你可以輕鬆地確定從一個請求到另一個請求所經過的時間。
  4. 資料長度 - 儲存在znode中的資料總量是資料長度。你最多可以儲存1MB的資料。

Znode的型別

Znode被分為持久(persistent)節點,順序(sequential)節點和臨時(ephemeral)節點。

  • 持久節點 - 即使在建立該特定znode的客戶端斷開連線後,持久節點仍然存在。預設情況下,除非另有說明,否則所有znode都是持久的。
  • 臨時節點 - 客戶端活躍時,臨時節點就是有效的。當客戶端與ZooKeeper集合斷開連線時,臨時節點會自動刪除。因此,只有臨時節點不允許有子節點。如果臨時節點被刪除,則下一個合適的節點將填充其位置。臨時節點在leader選舉中起著重要作用。
  • 順序節點 - 順序節點可以是持久的或臨時的。當一個新的znode被建立為一個順序節點時,ZooKeeper通過將10位的序列號附加到原始名稱來設定znode的路徑。例如,如果將具有路徑 /myapp 的znode建立為順序節點,則ZooKeeper會將路徑更改為 /myapp0000000001 ,並將下一個序列號設定為0000000002。如果兩個順序節點是同時建立的,那麼ZooKeeper不會對每個znode使用相同的數字。順序節點在鎖定和同步中起重要作用。

Sessions(會話)

  • 會話對於ZooKeeper的操作非常重要。會話中的請求按FIFO順序執行。一旦客戶端連線到伺服器,將建立會話並向客戶端分配會話ID 。
  • 客戶端以特定的時間間隔傳送心跳以保持會話有效。如果ZooKeeper集合在超過伺服器開啟時指定的期間(會話超時)都沒有從客戶端接收到心跳,則它會判定客戶端當機。
  • 會話超時通常以毫秒為單位。當會話由於任何原因結束時,在該會話期間建立的臨時節點也會被刪除。

Watches(監視)

  • 監視是一種簡單的機制,使客戶端收到關於ZooKeeper集合中的更改的通知。客戶端可以在讀取特定znode時設定Watches。Watches會向註冊的客戶端傳送任何znode(客戶端登錄檔)更改的通知。
  • Znode更改是與znode相關的資料的修改或znode的子項中的更改。只觸發一次watches。如果客戶端想要再次通知,則必須通過另一個讀取操作來完成。當連線會話過期時,客戶端將與伺服器斷開連線,相關的watches也將被刪除。

Zookeeper 工作流

一旦ZooKeeper集合啟動,它將等待客戶端連線。客戶端將連線到ZooKeeper集合中的一個節點。它可以是leader或follower節點。一旦客戶端被連線,節點將向特定客戶端分配會話ID並向該客戶端傳送確認。如果客戶端沒有收到確認,它將嘗試連線ZooKeeper集合中的另一個節點。 一旦連線到節點,客戶端將以有規律的間隔向節點傳送心跳,以確保連線不會丟失。

  • 如果客戶端想要讀取特定的znode,它將會向具有znode路徑的節點傳送讀取請求,並且節點通過從其自己的資料庫獲取來返回所請求的znode。為此,在ZooKeeper集合中讀取速度很快。
  • 如果客戶端想要將資料儲存在ZooKeeper集合中,則會將znode路徑和資料傳送到伺服器。連線的伺服器將該請求轉發給leader,然後leader將向所有的follower重新發出寫入請求。如果只有大部分節點成功響應,而寫入請求成功,則成功返回程式碼將被髮送到客戶端。 否則,寫入請求失敗。絕大多數節點被稱為 Quorum 。

ZooKeeper集合中的節點

  • 如果我們有單個節點,則當該節點故障時,ZooKeeper集合將故障。它有助於“單點故障",不建議在生產環境中使用。
  • 如果我們有兩個節點而一個節點故障,我們沒有佔多數,因為兩個中的一個不是多數。
  • 如果我們有三個節點而一個節點故障,那麼我們有大多數,因此,這是最低要求。ZooKeeper集合在實際生產環境中必須至少有三個節點。
  • 如果我們有四個節點而兩個節點故障,它將再次故障。類似於有三個節點,額外節點不用於任何目的,因此,最好新增奇數的節點,例如3,5,7。
  • 寫入過程比ZooKeeper集合中的讀取過程要貴,因為所有節點都需要在資料庫中寫入相同的資料

輸入圖片說明
螢幕截圖.png

寫入(write)

  • 寫入過程由leader節點處理。leader將寫入請求轉發到所有znode,並等待znode的回覆。如果一半的znode回覆,則寫入過程完成。

讀取(read)

  • 讀取由特定連線的znode在內部執行,因此不需要與叢集進行互動。

複製資料庫(replicated database)

  • 它用於在zookeeper中儲存資料。每個znode都有自己的資料庫,每個znode在一致性的幫助下每次都有相同的資料。

Leader負責處理寫入請求的Znode。

Follower:從客戶端接收寫入請求,並將它們轉發到leader znode。

請求處理器(request processor):只存在於leader節點。它管理來自follower節點的寫入請求。

原子廣播(atomic broadcasts):負責廣播從leader節點到follower節點的變化。

Zookeeper leader選舉

分析如何在ZooKeeper集合中選舉leader節點。考慮一個叢集中有N個節點。leader選舉的過程如下:

  • 所有節點建立具有相同路徑 /app/leader_election/guid_ 的順序、臨時節點。
  • ZooKeeper集合將附加10位序列號到路徑,建立的znode將是 /app/leader_election/guid_0000000001,/app/leader_election/guid_0000000002等。
  • 對於給定的例項,在znode中建立最小數字的節點成為leader,而所有其他節點是follower。
  • 每個follower節點監視下一個具有最小數字的znode。例如,建立znode/app/leader_election/guid_0000000008的節點將監視znode/app/leader_election/guid_0000000007,建立znode/app/leader_election/guid_0000000007的節點將監視znode/app/leader_election/guid_0000000006。
  • 如果leader關閉,則其相應的znode/app/leader_electionN會被刪除。
  • 下一個線上follower節點將通過監視器獲得關於leader移除的通知。
  • 下一個線上follower節點將檢查是否存在其他具有最小數字的znode。如果沒有,那麼它將承擔leader的角色。否則,它找到的建立具有最小數字的znode的節點將作為leader。
  • 類似地,所有其他follower節點選舉建立具有最小數字的znode的節點作為leader。

Zookeeper叢集安裝 安裝:

wget http://www.apache.org/dist//zookeeper/zookeeper-3.3.3/zookeeper-3.3.3.tar.gz
tar zxvf zookeeper-3.3.3.tar.gz
cd zookeeper-3.3.3
cp conf/zoo_sample.cfg conf/zoo.cfg
複製程式碼

zookeeper-3.4.10/conf新建立zoo.cfg,zoo2.cfg,zoo3.cfg三個檔案,配置如下,

#心跳間隔 毫秒每次
tickTime = 2000
##日誌位置 偽叢集設定不同目錄
dataDir = /home/zookeeper-3.4.10/data/data1
#監聽客戶端連線的埠 偽叢集設定不同埠
clientPort = 2181
#多少個心跳時間內,允許其他server連線並初始化資料,如果ZooKeeper管理的資料較大,則應相應增大這個值
initLimit = 10
#多少個tickTime內,允許follower同步,如果follower落後太多,則會被丟棄
syncLimit = 5

#偽叢集配置 不需要叢集去掉(vim /etc/host 對映ip的hostname的關係)
server.1=CentOS124:2886:3886
server.2=CentOS124:2888:3888
server.3=CentOS124:2889:3889
複製程式碼

並在zookeeper-3.4.10/data的 data1,data2,data3 目錄下放置myid檔案,檔案內容為1,2,3:

輸入圖片說明
螢幕截圖.png
輸入圖片說明
螢幕截圖.png

進入bi目錄 啟動

./zkServer.sh start zoo.cfg
./zkServer.sh start zoo2.cfg
./zkServer.sh start zoo3.cfg
複製程式碼

檢視服務狀態

./zkServer.sh status zoo.cfg
./zkServer.sh status zoo2.cfg
./zkServer.sh status zoo3.cfg
複製程式碼

使用Zookeeper的客戶端來連線並測試了

[root@CentOS124 bin]# ./zkCli.sh

#檢視根節點
[zk: localhost:2181(CONNECTED) 0] ls /
[firstNode, SecodeZnode, firstNode0000000002, hbase, zookeeper]
[zk: localhost:2181(CONNECTED) 0] create /mykey1 myvalue1  #建立一個新節點mykey1 
Created /mykey1
[zk: localhost:2181(CONNECTED) 1] get /mykey1   #獲取mykey1節點  

#要建立順序節點
create -s /FirstZnode second-data

#要建立臨時節點
create -e /SecondZnode “Ephemeral-data"
複製程式碼