Zookeeper 概述
ZooKeeper是一種分佈式協調服務,用於管理大型主機。在分佈式環境中協調和管理服務是一個複雜的過程。ZooKeeper經過其簡單的架構和API解決了這個問題。ZooKeeper容許開發人員專一於核心應用程序邏輯,而沒必要擔憂應用程序的分佈式特性。node
分佈式應用的優勢 算法
可靠性 - 單個或幾個系統的故障不會使整個系統出現故障。
可擴展性 - 能夠在須要時增長性能,經過添加更多機器,在應用程序配置中進行微小的更改,而不會有停機時間。
透明性 - 隱藏系統的複雜性,並將其顯示爲單個實體/應用程序。
分佈式應用的挑戰 數據庫
競爭條件 - 兩個或多個機器嘗試執行特定任務,實際上只需在任意給定時間由單個機器完成。例如,共享資源只能在任意給定時間由單個機器修改。
死鎖 - 兩個或多個操做等待彼此無限期完成。
不一致 - 數據的部分失敗。
什麼是Apache ZooKeeper?
Apache ZooKeeper是由集羣(節點組)使用的一種服務,用於在自身之間協調,並經過穩健的同步技術維護共享數據。ZooKeeper自己是一個分佈式應用程序,爲寫入分佈式應用程序提供服務。apache
ZooKeeper提供的常見服務以下 : vim
命名服務 - 按名稱標識集羣中的節點。它相似於DNS,但僅對於節點。
配置管理 - 加入節點的最近的和最新的系統配置信息。
集羣管理 - 實時地在集羣和節點狀態中加入/離開節點。
選舉算法 - 選舉一個節點做爲協調目的的leader。
鎖定和同步服務 - 在修改數據的同時鎖定數據。此機制可幫助你在鏈接其餘分佈式應用程序(如Apache HBase)時進行自動故障恢復。
高度可靠的數據註冊表 - 即便在一個或幾個節點關閉時也能夠得到數據。
ZooKeeper的好處
簡單的分佈式協調過程
同步 - 服務器進程之間的相互排斥和協做。此過程有助於Apache HBase進行配置管理。
有序的消息
序列化 - 根據特定規則對數據進行編碼。確保應用程序運行一致。這種方法能夠在MapReduce中用來協調隊列以執行運行的線程。
可靠性
原子性 - 數據轉移徹底成功或徹底失敗,但沒有事務是部分的。
ZooKeeper的架構
屏幕截圖.png
Client(客戶端) bash
客戶端,咱們的分佈式應用集羣中的一個節點,從服務器訪問信息。對於特定的時間間隔,每一個客戶端向服務器發送消息以使服務器知道客戶端是活躍的。相似地,當客戶端鏈接時,服務器發送確認碼。若是鏈接的服務器沒有響應,客戶端會自動將消息重定向到另外一個服務器。
Server(服務器) 服務器
服務器,咱們的ZooKeeper整體中的一個節點,爲客戶端提供全部的服務。向客戶端發送確認碼以告知服務器是活躍的。
Ensemble 架構
ZooKeeper服務器組。造成ensemble所需的最小節點數爲3。
Leader: app
服務器節點,若是任何鏈接的節點失敗,則執行自動恢復。Leader在服務啓動時被選舉。
Follower 分佈式
層次命名空間
ZooKeeper節點稱爲 znode 。每一個znode由一個名稱標識,並用路徑(/)序列分隔。
屏幕截圖.png
config 命名空間用於集中式配置管理,workers 命名空間用於命名。
在 config 命名空間下,每一個znode最多可存儲1MB的數據。這與UNIX文件系統相相似,除了父znode也能夠存儲數據。這種結構的主要目的是存儲同步數據並描述znode的元數據。此結構稱爲 ZooKeeper數據模型。
ZooKeeper數據模型中的每一個znode都維護着一個 stat 結構。一個stat僅提供一個znode的元數據。它由版本號,操做控制列表(ACL),時間戳和數據長度組成。
版本號 - 每一個znode都有版本號,這意味着每當與znode相關聯的數據發生變化時,其對應的版本號也會增長。當多個zookeeper客戶端嘗試在同一znode上執行操做時,版本號的使用就很重要。
操做控制列表(ACL) - ACL基本上是訪問znode的認證機制。它管理全部znode讀取和寫入操做。
時間戳 - 時間戳表示建立和修改znode所通過的時間。它一般以毫秒爲單位。ZooKeeper從「事務ID"(zxid)標識znode的每一個更改。Zxid是惟一的,而且爲每一個事務保留時間,以便你能夠輕鬆地肯定從一個請求到另外一個請求所通過的時間。
數據長度 - 存儲在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
initLimit = 10
syncLimit = 5
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]
[zk: localhost:2181(CONNECTED) 0] ls /
[firstNode, SecodeZnode, firstNode0000000002, hbase, zookeeper]
[zk: localhost:2181(CONNECTED) 0] create /mykey1 myvalue1
Created /mykey1
[zk: localhost:2181(CONNECTED) 1] get /mykey1
create -s /FirstZnode second-data
create -e /SecondZnode 「Ephemeral-data" 複製代碼