1. 程式人生 > >ZooKeeper系列之二:Zookeeper應用介紹與安裝部署大神必學

ZooKeeper系列之二:Zookeeper應用介紹與安裝部署大神必學

定性 前言 默認 即使 日誌 名稱 hosts too 臺電

前言
最近有很多粉絲反映怎麽學好java?Zookeepr是什麽? java開發技術不是一兩天就能學好的,Zookeepr也是一樣的道理,關鍵還得看你怎麽去學,跟誰去學,俗話說的好師傅領進門,修行靠個人,這個不是短時間類所能完成的任務,有想法的上方關註,下方留言“學習”我教你!
1 Zookeeper概述#
ZooKeeper是一個為分布式應用所設計的分布的、開源的協調服務,它主要是用來解決分布式應用中經常遇到的一些數據管理問題,簡化分布式應用協調及其管理的難度,提供高性能的分布式服務。ZooKeeper本身可以以Standalone模式安裝運行,不過它的長處在於通過分布式ZooKeeper集群(一個Leader,多個Follower),基於一定的策略來保證ZooKeeper集群的穩定性和可用性,從而實現分布式應用的可靠性。
在網上看到了一個很不錯的關於ZooKeeper的介紹: 顧名思義動物園管理員,他是拿來管大象(Hadoop) 、 蜜蜂(Hive) 、 小豬(Pig) 的管理員, Apache Hbase和 Apache Solr 以及LinkedIn sensei 等項目中都采用到了 Zookeeper。ZooKeeper是一個分布式的,開放源碼的分布式應用程序協調服務,ZooKeeper是以Fast Paxos算法為基礎,實現同步服務,配置維護和命名服務等分布式應用。
從介紹可以看出,ZooKeeper更傾向於對大型應用的協同維護管理工作。IBM則給出了IBM對ZooKeeper的認知: Zookeeper 分布式服務框架是 Apache Hadoop 的一個子項目,它主要是用來解決分布式應用中經常遇到的一些數據管理問題,如:統一命名服務、狀態同步服務、集群管理、分布式應用配置項的管理等。
總之,我認為它的核心詞就是一個單詞,協調。
2 Zookeeper特征#
在Hadoop權威指南中看到了關於ZooKeeper的一些核心特征,閱讀之後感覺總結的甚是精辟,在這裏引用並總結。
2.1 簡易##
ZooKeeper的最重要核心就是一個精簡文件系統,提供一些簡單的操作以及附加的抽象(例如排序和通知)。
2.2 易表達##
ZooKeeper的原型是一個豐富的集合,它們是一些已建好的塊,可以用來構建大型的協作數據結構和協議,例如:分布式隊列、分布式鎖以及一組對等體的選舉。
2.3 高可用性##
ZooKeeper運行在一些集群上,被設計成可用性較高的,因此應用程序可以依賴它。ZooKeeper可以幫助你的系統避免單點故障,從而建立一個可靠的應用程序。
2.4 松散耦合##
ZooKeeper的交互支持參與者之間並不了解對方。例如:ZooKeeper可以被當做一種公共的機制,使得進程彼此不知道對方的存在也可以相互發現並且交互,對等方可能甚至不是同步的。
這一特點我感覺最能體現在集群的部署啟動過程中。像Hadoop當把配置文件寫好之後,然後運行啟動腳本,則251,241,242中作為集群的虛擬機是同步啟動的,也就是DataNode,NameNode,TaskTracker,以及JobTracker的啟動並運行時在一次啟動過程中啟動的,就是運行一次啟動腳本文件,則都啟動起來。但是ZooKeeper的啟動過程卻不是這樣的。我在251,241,242部署了ZooKeeper集群,並進行啟動,則啟動的過程是這樣的:首先ssh到251然後啟動,這時候251的集群節點啟動起來,但是控制臺一直報錯,大概的含義就是沒有檢測到其他兩個結點。接著分別ssh到241,242,分別啟動集群中的剩下的結點,當241啟動起來時,回到251查看,發現報錯的信息減少,意思是只差一個結點。當251,241,242三臺服務器的結點全部啟動起來,則三臺的服務器的控制臺打印出正常的信息。
2.5 一個庫##
ZooKeeper提供了一個開源的、共享的執行存儲,以及通用協作的方法,分擔了每個程序員寫通用協議的負擔。隨著時間的推移,人們可以增加和改進這個庫來滿足自己的需求。
3 為什麽使用Zookeeper#
記得在大約在2006年的時候Google出了Chubby來解決分布一致性的問題(distributed consensus problem),所有集群中的服務器通過Chubby最終選出一個Master Server ,最後這個Master Server來協調工作。簡單來說其原理就是:在一個分布式系統中,有一組服務器在運行同樣的程序,它們需要確定一個Value,以那個服務器提供的信息為主/為準,當這個服務器經過n/2+1的方式被選出來後,所有的機器上的Process都會被通知到這個服務器就是主服務器 Master服務器,大家以他提供的信息為準。很想知道Google Chubby中的奧妙,可惜人家Google不開源,自家用。
但是在2009年3年以後沈默已久的Yahoo在Apache上推出了類似的產品ZooKeeper,並且在Google原有Chubby的設計思想上做了一些改進,因為ZooKeeper並不是完全遵循Paxos協議,而是基於自身設計並優化的一個2 phase commit的協議,如圖所示:

image.png
ZooKeeper跟Chubby一樣用來存放一些相互協作的信息(Coordination),這些信息比較小一般不會超過1M,在zookeeper中是以一種hierarchical tree的形式來存放,這些具體的Key/Value信息就store在tree node中。
當有事件導致node數據,例如:變更,增加,刪除時,Zookeeper就會調用 triggerWatch方法,判斷當前的path來是否有對應的監聽者(watcher),如果有watcher,會觸發其process方法,執行process方法中的業務邏輯,如圖:

image.png
3.1 應用實例##
ZooKeeper有了上述的這些用途,讓我們設想一下,在一個分布式系統中有這這樣的一個應用:
2個任務工廠(Task Factory)一主一從,如果從的發現主的死了以後,從的就開始工作,他的工作就是向下面很多臺代理(Agent)發送指令,讓每臺代理(Agent)獲得不同的賬戶進行分布式並行計算,而每臺代理(Agent)中將分配很多帳號,如果其中一臺代理(Agent)死掉了,那麽這臺死掉的代理上的賬戶就不會繼續工作了。上述,出現了3個最主要的問題:

Task Factory 主/從一致性的問題;
Task Factory 主/從心跳如何用簡單+穩定 或者2者折中的方式實現;
一臺代理(Agent)死掉了以後,一部分的賬戶就無法繼續工作,需要通知所有在線的代理(Agent)重新分配一次帳號;

image.png
OK,讓我們想想ZooKeeper是不是能幫助我們去解決目前遇到的這3個最主要的問題呢?

任務工廠Task Factory都連接到ZooKeeper上,創建節點,設置對這個節點進行監控,監控方法例如:
event= new WatchedEvent(EventType.NodeDeleted, KeeperState.SyncConnected, "/TaskFactory");
這個方法的意思就是只要Task Factory與zookeeper斷開連接後,這個節點就會被自動刪除。

原來主的任務工廠斷開了TCP連接,這個被創建的/TaskFactory節點就不存在了,而且另外一個連接在上面的Task Factory可以立刻收到這個事件(Event),知道這個節點不存在了,也就是說主TaskFactory死了。
接下來另外一個活著的TaskFactory會再次創建/TaskFactory節點,並且寫入自己的ip到znode裏面,作為新的標記。
此時Agents也會知道主的TaskFactory不工作了,為了防止系統中大量的拋出異常,他們將會先把自己手上的事情做完,然後掛起,等待收到Zookeeper上重新創建一個/TaskFactory節點,收到 EventType.NodeCreated 類型的事件將會繼續工作。
原來從的TaskFactory 將自己變成一個主TaskFactory,當系統管理員啟動原來死掉的主的TaskFactory,世界又恢復平靜了。
如果一臺代理死掉,其他代理他們將會先把自己手上的事情做完,然後掛起,向TaskFactory發送請求,TaskFactory會重新分配(sharding)帳戶到每個Agent上了,繼續工作。
上述內容,大致如圖所示:

image.png
4 Zookeeper基本知識#
4.1 層次化的名字空間##
ZooKeeper的整個名字空間的結構是層次化的,和一般的Linux文件系統結構非常相似,一顆很大的樹。這也就是ZooKeeper的數據結構情況。名字空間的層次由斜杠/來進行分割,在名稱空間裏面的每一個結點的名字空間唯一由這個結點的路徑來確定。
每一個節點擁有自身的一些信息,包括:數據、數據長度、創建時間、修改時間等等。從這樣一類既含有數據,又作為路徑表標示的節點的特點中,可以看出,ZooKeeper的節點既可以被看做是一個文件,又可以被看做是一個目錄,它同時具有二者的特點。為了便於表達,今後我們將使用Znode來表示所討論的ZooKeeper節點。
4.2 Znode##
Znode維護著數據、ACL(access control list,訪問控制列表)、時間戳等交換版本號等數據結構,它通過對這些數據的管理來讓緩存生效並且令協調更新。每當Znode中的數據更新後它所維護的版本號將增加,這非常類似於數據庫中計數器時間戳的操作方式。
另外Znode還具有原子性操作的特點:命名空間中,每一個Znode的數據將被原子地讀寫。讀操作將讀取與Znode相關的所有數據,寫操作將替換掉所有的數據。除此之外,每一個節點都有一個訪問控制列表,這個訪問控制列表規定了用戶操作的權限。
ZooKeeper中同樣存在臨時節點。這些節點與session同時存在,當session生命周期結束,這些臨時節點也將被刪除。臨時節點在某些場合也發揮著非常重要的作用。
4.3 Watch機制##
Watch機制就和單詞本身的意思一樣,看。看什麽?具體來講就是某一個或者一些Znode的變化。官方給出的定義:一個Watch事件是一個一次性的觸發器,當被設置了Watch的數據發生了改變的時候,則服務器將這個改變發送給設置了Watch的客戶端,以便通知它們。
Watch機制主要有以下三個特點:

一次性的觸發器(one-time trigger)
當數據改變的時候,那麽一個Watch事件會產生並且被發送到客戶端中。但是客戶端只會收到一次這樣的通知,如果以後這個數據再次發生改變的時候,之前設置Watch的客戶端將不會再次收到改變的通知,因為Watch機制規定了它是一個一次性的觸發器。
當設置監視的數據發生改變時,該監視事件會被發送到客戶端,例如,如果客戶端調用了 getData("/znode1", true) 並且稍後 /znode1 節點上的數據發生了改變或者被刪除了,客戶端將會獲取到 /znode1 發生變化的監視事件,而如果 /znode1 再一次發生了變化,除非客戶端再次對 /znode1 設置監視,否則客戶端不會收到事件通知。

發送給客戶端(Sent to the client)
這個表明了Watch的通知事件是從服務器發送給客戶端的,是異步的,這就表明不同的客戶端收到的Watch的時間可能不同,但是ZooKeeper有保證:當一個客戶端在看到Watch事件之前是不會看到結點數據的變化的。例如:A=3,此時在上面設置了一次Watch,如果A突然變成4了,那麽客戶端會先收到Watch事件的通知,然後才會看到A=4。
Zookeeper 客戶端和服務端是通過 Socket 進行通信的,由於網絡存在故障,所以監視事件很有可能不會成功地到達客戶端,監視事件是異步發送至監視者的,Zookeeper 本身提供了保序性(ordering guarantee):即客戶端只有首先看到了監視事件後,才會感知到它所設置監視的 znode 發生了變化(a client will never see a change for which it has set a watch until it first sees the watch event). 網絡延遲或者其他因素可能導致不同的客戶端在不同的時刻感知某一監視事件,但是不同的客戶端所看到的一切具有一致的順序。

被設置Watch的數據(The data for which the watch was set)
這意味著 znode 節點本身具有不同的改變方式。你也可以想象 Zookeeper 維護了兩條監視鏈表:數據監視和子節點監視(data watches and child watches) getData() and exists() 設置數據監視,getChildren() 設置子節點監視。 或者,你也可以想象 Zookeeper 設置的不同監視返回不同的數據,getData() 和 exists() 返回 znode 節點的相關信息,而 getChildren() 返回子節點列表。因此, setData() 會觸發設置在某一節點上所設置的數據監視(假定數據設置成功),而一次成功的 create() 操作則會出發當前節點上所設置的數據監視以及父節點的子節點監視。一次成功的 delete() 操作將會觸發當前節點的數據監視和子節點監視事件,同時也會觸發該節點父節點的child watch。
Zookeeper 中的監視是輕量級的,因此容易設置、維護和分發。當客戶端與 Zookeeper 服務器端失去聯系時,客戶端並不會收到監視事件的通知,只有當客戶端重新連接後,若在必要的情況下,以前註冊的監視會重新被註冊並觸發,對於開發人員來說 這通常是透明的。只有一種情況會導致監視事件的丟失,即:通過 exists() 設置了某個 znode 節點的監視,但是如果某個客戶端在此 znode 節點被創建和刪除的時間間隔內與 zookeeper 服務器失去了聯系,該客戶端即使稍後重新連接 zookeeper服務器後也得不到事件通知。
4.4 ACL訪問控制列表##
這是另外一個和Linux操作系統非常相似的地方,ZooKeeper使用ACL來控制對旗下Znode結點們的訪問。ACL的實現和Linux文件系統的訪問權限十分類似:它通過設置權限為來表明是否允許對一個結點的相關內容的改變。
但是與傳統Linux機制不太相同,一個結點的數據沒有類似“擁有者,組用戶,其他用戶”的概念,在ZooKeeper中,ACL通過設置ID以及與其關聯的權限來完成訪問控制的。ACL的權限組成語法是:
(scheme:expression, perms)
前者表明設置的ID,逗號後面表示的是ID相關的權限,例如:
(ip:172.16.16.1,READ)
指明了IP地址為如上的用戶的權限為只讀。
以下列舉以下ACL所具有的權限:
CREATE:表明你可以創建一個Znode的子結點。 READ:你可以得到這個結點的數據以及列舉該結點的子結點情況。 WRITE:設置一個結點的數據。 DELETE:可以刪除一個結點 ADMIN:對一個結點設置權限。
5 Zookeeper部署#
ZooKeeper的部署方式主要有三種,單機模式、偽集群模式、集群模式。其實剩下的兩種模式都是集群模式的特殊情況。
5.1 系統環境##

系統環境
5.2 下載Zookeeper##

mkdir /home/taomk/zk 創建文件夾
cd /home/taomk/zk; wget http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz 下載
tar xvf zookeeper-3.4.6.tar.gz 解壓縮
mv zookeeper-3.4.6 zookeeper346 重命名
cd zookeeper346; ls -l

image.png
5.3 配置環境變量##
export ZOOKEEPER_HOME=/home/taomk/zk/zookeeper346 export PATH=$PATH:$ZOOKEEPER_HOME/bin:$ZOOKEEPER_HOME/conf
5.4 ZooKeeper的單機模式部署##
ZooKeeper的單機模式通常是用來快速測試客戶端應用程序的,在實際過程中不可能是單機模式。單機模式的配置也比較簡單。

編寫配置文件zoo.cfg:ZooKeeper的運行默認是讀取zoo.cfg文件裏面的內容的。
~mkdir /home/taomk/zk/zoo/zk0 ~cp conf/zoo_sample.cfg conf/zk0.cfg ~vim conf/zk0.cfg tickTime=2000 initLimit=10 syncLimit=5 dataDir=/home/conan/zoo/zk0 clientPort=2181
在zk0.cfg這個文件中,我們需要指定 dataDir 的值,它指向了一個目錄,這個目錄在開始的時候需要為空。下面是每個參數的含義:
tickTime :基本事件單元,以毫秒為單位。這個時間是作為 Zookeeper 服務器之間或客戶端與服務器之間維持心跳的時間間隔,也就是每個 tickTime 時間就會發送一個心跳。
dataDir :存儲內存中數據庫快照的位置,顧名思義就是 Zookeeper 保存數據的目錄,默認情況下,Zookeeper 將寫數據的日誌文件也保存在這個目錄裏。
clientPort :這個端口就是客戶端連接 Zookeeper 服務器的端口,Zookeeper 會監聽這個端口,接受客戶端的訪問請求。
使用單機模式時用戶需要註意:這種配置方式下沒有 ZooKeeper 副本,所以如果 ZooKeeper 服務器出現故障, ZooKeeper 服務將會停止。

啟動Zookeeper
~bin/zkServer.sh start zk0.cfg

image.png
zk的服務顯示為QuorumPeerMain:
~jps 5321 QuorumPeerMain 5338 Jps
查看運行狀態:
~bin/zkServer.sh status zk0.cfg JMX enabled by default Using config: /home/taomk/zk/zookeeper346/bin/../conf/zk0.cfg Mode: standalone
單節點的時,Mode會顯示為standalone。

停止ZooKeeper服務
~ bin/zkServer.sh stop zk0.cfg JMX enabled by default Using config: /home/taomk/zk/zookeeper346/bin/../conf/zk0.cfg Stopping zookeeper ... STOPPED
5.5 ZooKeeper的偽集群模式部署##
所謂 “偽分布式集群” 就是在,在一臺PC中,啟動多個ZooKeeper的實例。“完全分布式集群” 是每臺PC,啟動一個ZooKeeper實例。其實在企業中式不會存在的,另外為了測試一個客戶端程序也沒有必要存在,只有在物質條件比較匱乏的條件下才會存在的模式。集群偽分布模式就是在單機下模擬集群的ZooKeeper服務,在一臺機器上面有多個ZooKeeper的JVM同時運行。
ZooKeeper的集群模式下,多個Zookeeper服務器在工作前會選舉出一個Leader,在接下來的工作中這個被選舉出來的Leader死了,而剩下的Zookeeper服務器會知道這個Leader死掉了,在活著的Zookeeper集群中會繼續選出一個Leader,選舉出Leader的目的是為了可以在分布式的環境中保證數據的一致性。

確認集群服務器的數量
由於ZooKeeper集群中,會有一個Leader負責管理和協調其他集群服務器,因此服務器的數量通常都是單數,例如3,5,7...等,這樣2n+1的數量的服務器就可以允許最多n臺服務器的失效。

創建環境目錄
~ mkdir /home/taomk/zk/zoo/zk1 ~ mkdir /home/taomk/zk/zoo/zk2 ~ mkdir /home/taomk/zk/zoo/zk3 #新建myid文件 ~ echo "1" > /home/taomk/zk/zoo/zk1/myid ~ echo "2" > /home/taomk/zk/zoo/zk2/myid ~ echo "3" > /home/taomk/zk/zoo/zk3/myid

分別修改配置文件
修改:dataDir,clientPort
增加:集群的實例,server.X,”X”表示每個目錄中的myid的值
~ vim /home/taomk/zk/zookeeper346/conf/zk1.cfg tickTime=2000 initLimit=10 syncLimit=5 dataDir=/home/taomk/zk/zoo/zk1 clientPort=2181 server.1=127.0.0.1:2888:3888 server.2=127.0.0.1:2889:3889 server.3=127.0.0.1:2890:3890 ~ vim /home/taomk/zk/zookeeper346/conf/zk2.cfg tickTime=2000 initLimit=10 syncLimit=5 dataDir=/home/taomk/zk/zoo/zk2 clientPort=2182 server.1=127.0.0.1:2888:3888 server.2=127.0.0.1:2889:3889 server.3=127.0.0.1:2890:3890 ~ vim /home/taomk/zk/zookeeper346/conf/zk3.cfg tickTime=2000 initLimit=10 syncLimit=5 dataDir=/home/taomk/zk/zoo/zk3 clientPort=2183 server.1=127.0.0.1:2888:3888 server.2=127.0.0.1:2889:3889 server.3=127.0.0.1:2890:3890
initLimit:這個配置項是用來配置 Zookeeper 接受客戶端(這裏所說的客戶端不是用戶連接 Zookeeper 服務器的客戶端,而是 Zookeeper 服務器集群中連接到 Leader 的 Follower 服務器)初始化連接時最長能忍受多少個心跳時間間隔數。當已經超過 10 個心跳的時間(也就是 tickTime)長度後 Zookeeper 服務器還沒有收到客戶端的返回信息,那麽表明這個客戶端連接失敗。總的時間長度就是 102000=20 秒。
syncLimit:這個配置項標識 Leader 與 Follower 之間發送消息,請求和應答時間長度,最長不能超過多少個 tickTime 的時間長度,總的時間長度就是 5
2000=10 秒。
server.A=B:C:D:其中 A 是一個數字,表示這個是第幾號服務器,就是集群模式下配置的myid文件所存放的數值;B 是這個服務器的 ip 地址;C 表示的是這個服務器與集群中的 Leader 服務器交換信息的端口;D 表示的是萬一集群中的 Leader 服務器掛了,需要一個端口來重新進行選舉,選出一個新的 Leader,而這個端口就是用來執行選舉時服務器相互通信的端口。如果是偽集群的配置方式,由於 B 都是一樣,所以不同的 Zookeeper 實例通信端口號不能一樣,所以要給它們分配不同的端口號。
由於三個服務都在同一臺電腦上,因此這裏要保證地址的唯一性,因此要特別註意IP地址和端口號不要互相沖突,以免影響程序的正確執行。
3個節點的ZooKeeper集群配置完成,接下來我們的啟動服務。

啟動集群
~ bin/zkServer.sh start zk1.cfg ~ bin/zkServer.sh start zk2.cfg ~ bin/zkServer.sh start zk3.cfg ~ jps 5422 QuorumPeerMain 5395 QuorumPeerMain 5463 QuorumPeerMain 5494 Jps #查看節點狀態 ~ bin/zkServer.sh status zk1.cfg JMX enabled by default Using config: /home/taomk/zk/zookeeper346/bin/../conf/zk1.cfg Mode: follower ~ bin/zkServer.sh status zk2.cfg JMX enabled by default Using config: /home/taomk/zk/zookeeper346/bin/../conf/zk2.cfg Mode: leader ~ bin/zkServer.sh status zk3.cfg JMX enabled by default Using config: /home/taomk/zk/zookeeper346/bin/../conf/zk3.cfg Mode: follower

查看ZooKeeper物理文件目錄結構
~ tree -L 3 /home/taomk/zk/zoo

image.png
5.6 ZooKeeper Distributed模式##
ZooKeeper分布式模式安裝(ZooKeeper集群)也比較容易,這裏說明一下基本要點。
首先要明確的是,ZooKeeper集群是一個獨立的分布式協調服務集群,“獨立”的含義就是說,如果想使用ZooKeeper實現分布式應用的協調與管理,簡化協調與管理,任何分布式應用都可以使用,這就要歸功於Zookeeper的數據模型(Data Model)和層次命名空間(Hierarchical Namespace)結構,在設計你的分布式應用協調服務時,首要的就是考慮如何組織層次命名空間。
下面說明分布式模式的安裝配置,過程如下所示:

第一步:主機名稱到IP地址映射配置
ZooKeeper集群中具有兩個關鍵的角色:Leader和Follower。集群中所有的結點作為一個整體對分布式應用提供服務,集群中每個結點之間都互相連接,所以,在配置的ZooKeeper集群的時候,每一個結點的host到IP地址的映射都要配置上集群中其它結點的映射信息。
例如,ZooKeeper集群中每個結點的配置,以slave-01為例,/etc/hosts內容如下所示:
192.168.0.179 slave-01 192.168.0.178 slave-02 192.168.0.177 slave-03
ZooKeeper采用一種稱為Leader election的選舉算法。在整個集群運行過程中,只有一個Leader,其他的都是Follower,如果ZooKeeper集群在運行過程中Leader出了問題,系統會采用該算法重新選出一個Leader。因此,各個結點之間要能夠保證互相連接,必須配置上述映射。
ZooKeeper集群啟動的時候,會首先選出一個Leader,在Leader election過程中,某一個滿足選舉算法的結點就能成為Leader。

第二步:修改ZooKeeper配置文件
在其中一臺機器(slave-01)上,解壓縮zookeeper-3.3.4.tar.gz,修改配置文件conf/zoo.cfg,內容如下所示:
tickTime=2000 dataDir=/home/hadoop/storage/zookeeper clientPort=2181 initLimit=5 syncLimit=2 server.1=slave-01:2888:3888 server.2=slave-02:2888:3888 server.3=slave-03:2888:3888

第三步:遠程復制分發安裝文件
上面已經在一臺機器slave-01上配置完成ZooKeeper,現在可以將該配置好的安裝文件遠程拷貝到集群中的各個結點對應的目錄下:
cd /home/hadoop/installation/ scp -r zookeeper-3.3.4/ [email protected]:/home/hadoop/installation/ scp -r zookeeper-3.3.4/ [email protected]:/home/hadoop/installation/

第四步:設置myid
在我們配置的dataDir指定的目錄下面,創建一個myid文件,裏面內容為一個數字,用來標識當前主機,conf/zoo.cfg文件中配置的server.X中X為什麽數字,則myid文件中就輸入這個數字,例如:
[email protected]:~/installation/zookeeper-3.3.4$ echo "1" > /home/hadoop/storage/zookeeper/myid [email protected]:~/installation/zookeeper-3.3.4$ echo "2" > /home/hadoop/storage/zookeeper/myid [email protected]:~/installation/zookeeper-3.3.4$ echo "3" > /home/hadoop/storage/zookeeper/myid

第五步:啟動ZooKeeper集群
在ZooKeeper集群的每個結點上,執行啟動ZooKeeper服務的腳本,如下所示:
[email protected]:~/installation/zookeeper-3.3.4$ bin/zkServer.sh start [email protected]:~/installation/zookeeper-3.3.4$ bin/zkServer.sh start [email protected]:~/installation/zookeeper-3.3.4$ bin/zkServer.sh start
啟動的順序是slave-01>slave-02>slave-03,由於ZooKeeper集群啟動的時候,每個結點都試圖去連接集群中的其它結點,先啟動的肯定連不上後面還沒啟動的,所以日誌前面部分的異常是可以忽略的。通過後面部分可以看到,集群在選出一個Leader後,最後穩定了。其他結點可能也出現類似問題,屬於正常。
6 Zookeeper命令行操作#
ZooKeeper命令行工具類似於Linux的shell環境,不過功能肯定不及shell啦,但是使用它我們可以簡單的對ZooKeeper進行訪問,數據創建,數據修改等操作。
對於客戶端來說,ZooKeeper是一個整體(ensemble),連接到ZooKeeper集群實際上感覺在獨享整個集群的服務,所以,你可以在任何一個結點上建立到服務集群的連接。
當啟動 ZooKeeper 服務成功之後,輸入下述命令,連接到 ZooKeeper 服務:
~ bin/zkCli.sh –server 127.0.0.1:2181
連接成功後,系統會輸出 ZooKeeper 的相關環境以及配置信息,並在屏幕輸出“ Welcome to ZooKeeper ”等信息。
命令行工具的一些簡單操作如下:

使用 ls 命令來查看當前 ZooKeeper 中所包含的內容:
ls /

image.png

創建一個新的 znode ,使用 create /zk myData 。這個命令創建了一個新的 znode 節點“ zk ”以及與它關聯的字符串:
create /zk "myData"

image.png

運行 get 命令來確認 znode 是否包含我們所創建的字符串:
get /zk

image.png

通過 set 命令來對 zk 所關聯的字符串進行設置:
set /zk "zsl" get /zk

image.png

znode 刪除:
delete /zk

通過help打印命令行幫助:

image.png

退出客戶端連接:
quit
7 Java編程現實命令行操作#

ZkDemo.java :
public class ZkDemo { public static void main(String[] args) throws IOException, KeeperException, InterruptedException { // 創建一個與服務器的連接 ZooKeeper zk = new ZooKeeper("127.0.0.1:2181", 60000, new Watcher() { // 監控所有被觸發的事件 public void process(WatchedEvent event) { System.out.println("EVENT:" + event.getType()); } }); // 查看根節點 System.out.println("ls / => " + zk.getChildren("/", true)); // 創建一個目錄節點 if (zk.exists("/node", true) == null) { zk.create("/node", "conan".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println("create /node conan"); // 查看/node節點數據 System.out.println("get /node => " + new String(zk.getData("/node", false, null))); // 查看根節點 System.out.println("ls / => " + zk.getChildren("/", true)); } // 創建一個子目錄節點 if (zk.exists("/node/sub1", true) == null) { zk.create("/node/sub1", "sub1".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println("create /node/sub1 sub1"); // 查看node節點 System.out.println("ls /node => " + zk.getChildren("/node", true)); } // 修改節點數據 if (zk.exists("/node", true) != null) { zk.setData("/node", "changed".getBytes(), -1); // 查看/node節點數據 System.out.println("get /node => " + new String(zk.getData("/node", false, null))); } // 刪除節點 if (zk.exists("/node/sub1", true) != null) { zk.delete("/node/sub1", -1); zk.delete("/node", -1); // 查看根節點 System.out.println("ls / => " + zk.getChildren("/", true)); } // 關閉連接 zk.close(); } }

pom.xml,maven配置文件:
<dependencies> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.6</version> <exclusions> <exclusion> <groupId>javax.jms</groupId> <artifactId>jms</artifactId> </exclusion> <exclusion> <groupId>com.sun.jdmk</groupId> <artifactId>jmxtools</artifactId> </exclusion> <exclusion> <groupId>com.sun.jmx</groupId> <artifactId>jmxri</artifactId> </exclusion> </exclusions> </dependency> </dependencies>

ZooKeeper系列之二:Zookeeper應用介紹與安裝部署大神必學