1、ZooKeeper概述html
ZooKeeper是一種爲分佈式應用所設計的高可用、高性能且一致的開源協調服務,是Google的Chubby一個開源實現,是Hadoop和Hbase的重要組件,它提供了一項基本服務:分佈式鎖服務。因爲ZooKeeper的開源特性,後來咱們的開發者在分佈式鎖的基礎上,摸索了出了其餘的使用方法:配置維護、組服務、分佈式消息隊列、分佈式通知/協調等。node
zookeeper是基於內存同步數據的,因此集羣內的節點其內存中的數據結構是徹底相同的,所以效率很是高。數據庫
ZooKeeper具有的幾個特色決定了它可以用在大型的、分佈式的系統當中:apache
順序一致性bash
從同一個客戶端發起的事務請求,最終將會嚴格按照其發起順序被應用到zookeeper中服務器
原子性網絡
全部事物請求的處理結果在整個集羣中全部機器上的應用狀況是一致的,即,要麼整個集羣中全部機器都成功應用了某一事務,要麼都沒有應用,必定不會出現集羣中部分機器應用了改事務,另一部分沒有應用的狀況。session
單一視圖數據結構
不管客戶端鏈接的是哪一個zookeeper服務器,其看到的服務端數據模型都是一致的。併發
可靠性
一旦服務端成功的應用了一個事務,並完成對客戶端的響應,那麼該事務所引發的服務端狀態變動將會一直保留下來,除非有另外一個事務又對其進行了改變。
實時性
zookeeper並非一種強一致性,只能保證順序一致性和最終一致性,只能稱爲達到了僞實時性。
2、zookeeper 數據模型
ZooKeeper擁有一個層次的命名空間,這個和標準的文件系統很是類似,如圖:
ZooKeeper採用樹形層次結構,樹中的每一個節點被稱爲—Znode,Znode也能夠擁有子節點。
引用方式:
Zonde經過路徑引用,如同Unix中的文件路徑。必須是絕對路徑,所以他們必須由斜槓字符來開頭。除此之外,他們必須是惟一的,也就是說每個路徑只有一個表示,所以這些路徑不能改變。在ZooKeeper中,路徑由Unicode字符串組成,而且有一些限制。字符串"/zookeeper"用以保存管理信息,好比關鍵配額信息。
Znode 結構
ZooKeeper命名空間中的Znode,兼具文件和目錄兩種特色。既像文件同樣維護着數據、元信息、ACL、時間戳等數據結構,又像目錄同樣能夠做爲路徑標識的一部分。每一個Znode由3部分組成 :
一、stat:此爲狀態信息, 描述該Znode的版本, 權限等信息
二、data:與該Znode關聯的數據
三、children:該Znode下的子節點
ZooKeeper雖然能夠關聯一些數據,但並無被設計爲常規的數據庫或者大數據存儲,相反的是,它用來管理調度數據,好比分佈式應用中的配置文件信息、狀態信息、聚集位置等等。這些數據的共同特性就是它們都是很小的數據,一般以KB爲大小單位。ZooKeeper的服務器和客戶端都被設計爲嚴格檢查並限制每一個Znode的數據大小至多1M,但常規使用中應該遠小於此值。
3、節點類型
ZooKeeper中的節點有兩種,分別爲臨時節點和永久節點。節點的類型在建立時即被肯定,而且不能改變。
臨時節點:該節點的生命週期依賴於建立它們的會話。一旦會話(Session)結束,臨時節點將被自動刪除,固然能夠也能夠手動刪除。雖然每一個臨時的Znode都會綁定到一個客戶端會話,但他們對全部的客戶端仍是可見的。另外,ZooKeeper的臨時節點不容許擁有子節點。
永久節點:該節點的生命週期不依賴於會話,而且只有在客戶端顯示執行刪除操做的時候,他們才能被刪除。
順序節點
當建立Znode的時候,用戶能夠請求在ZooKeeper的路徑結尾添加一個遞增的計數。這個計數對於此節點的父節點來講是惟一的,它的格式爲"%10d"(10位數字,沒有數值的數位用0補充,例如"0000000001")。當計數值大於232-1時,計數器將溢出。
監視器
客戶端能夠在節點上設置watch,咱們稱之爲監視器。當節點狀態發生改變時(Znode的增、刪、改)將會觸發watch所對應的操做。當watch被觸發時,ZooKeeper將會向客戶端發送且僅發送一條通知,由於watch只能被觸發一次,這樣能夠減小網絡流量。
ZooKeeper有多種記錄時間的形式,其中包含如下幾個主要屬性:
(1) Zxid
導致ZooKeeper節點狀態改變的每個操做都將使節點接收到一個Zxid格式的時間戳,而且這個時間戳全局有序。也就是說,也就是說,每一個對節點的改變都將產生一個惟一的Zxid。若是Zxid1的值小於Zxid2的值,那麼Zxid1所對應的事件發生在Zxid2所對應的事件以前。實際上,ZooKeeper的每一個節點維護者三個Zxid值,爲別爲:cZxid、mZxid、pZxid。
一、cZxid: 是節點的建立時間所對應的Zxid格式時間戳。
二、mZxid:是節點的修改時間所對應的Zxid格式時間戳。
實現中Zxid是一個64爲的數字,它高32位是epoch用來標識leader關係是否改變,每次一個leader被選出來,它都會有一個 新的epoch。低32位是個遞增計數。
(2) 版本號
對節點的每個操做都將導致這個節點的版本號增長。每一個節點維護着三個版本號,他們分別爲:
一、version:節點數據版本號
二、cversion:子節點版本號
三、aversion:節點所擁有的ACL版本號
ZooKeeper節點屬性:
4、ZooKeeper 安裝配置
ZooKeeper的工做模式有三種:單機模式、集羣模式、僞集羣模式。
單機模式:Zookeeper只運行在一臺服務器上,適合測試環境;
僞集羣模式:就是在一臺物理機上運行多個Zookeeper 實例;
集羣模式:Zookeeper運行於一個至少有三個節點以上集羣中,適合生產環境;
Zookeeper經過複製來實現高可用性,只要集羣中半數以上的節點處於可用狀態,它就可以保證服務繼續。爲何必定要超過半數呢?這跟Zookeeper的複製策略有關:zookeeper確保對znode 樹的每個修改都會被複制到集羣中超過半數的節點上。
服務器角色有兩種:
一、leader -主節點
二、follower -從節點
在一個集羣中一般只有一個leader和多個follower,當leader下線時,follower能根據選舉策略,選舉一個新的leader保證集羣的正常工做。
下面咱們來構建一個單機模式的ZooKeeper節點:
能夠去Apache的鏡像站點下載zookeeper: http://www.apache.org/dyn/closer.cgi/zookeeper/
安裝ZooKeeper以前首先須要安裝JDK,在oracle官網能夠下載到。(建議下載rpm包安裝)
一、解壓zookeeper
tar xf zookeeper-3.4.9.tar.gz cd zookeeper-3.4.9
二、建立配置文件
# conf/zoo.cfg tickTime=2000 dataDir=/tmp/zookeeper clientPort=2181
三、啓動服務
bin/zkServer.sh start
ZooKeeper僞集羣模式
ZooKeeper提供了僞集羣模式,也就是能夠在同一臺機器上啓動多個zookeeper服務,當手頭機器不足時,又須要作實驗,提供了很大的便利。
注: 在同一臺機器上部署3個zookeeper server時,須要爲每一個server建立獨立的配置文件,而且保證每一個配置文件中的端口不能衝突,除了clientPort不一樣以外,另外,還要在dataDir所對應的目錄中建立myid文件來指定對應的zookeeper server 實例。
須要注意的幾個配置項:
clientPort端口:若是在1臺機器上部署多個server,那麼每臺機器都要不一樣的 clientPort,好比 server1是2181,server2是2182,server3是2183
dataDir和dataLogDir:dataDir和dataLogDir也須要區分下,將數據文件和日誌文件分開存放,同時每一個server的這兩變量所對應的路徑都是不一樣的
server.X和myid: server.X 這個數字就是對應,data/myid中的數字。在3個server的myid文件中分別寫入了0,1,2,那麼每一個server中的zoo.cfg都配 server.0 server.2,server.3就好了。由於在同一臺機器上,後面連着的2個端口,3個server都不要同樣,不然端口衝突
啓動命令
# 這時使用單機模式的啓動命令是不行的,須要在指令後面跟上不一樣實例的配置文件名稱。以下: bin/zkServer.sh start zoo1.cfg bin/zkServer.sh start zoo2.cfg bin/zkServer.sh start zoo3.cfg
5、集羣實戰 — 構建一個3節點的 ZooKeeper 集羣
實驗環境:
服務器IP | myid |
192.168.1.21 |
11 |
192.168.1.22 | 12 |
192.168.1.23 | 13 |
注:
(1) zk服務器集羣規模不得小於3個節點
(2) 要求各服務器之間系統時間要保持一致。
爲了實現高可用的ZooKeeper服務,應該把zk部署在一個集羣中,每臺機器只跑一個zk實例。配置方式和前面差很少,只是每臺機器上的配置文件 conf/zoo.cfg 徹底相同。
建立myid
# 爲每臺機器建立myid文件 # 192.168.1.21 echo 11 >/u01/zookeeper/zookeeper-3.4.9/data/myid # 192.168.1.22 echo 12 >/u01/zookeeper/zookeeper-3.4.9/data/myid # 192.168.1.23 echo 13 >/u01/zookeeper/zookeeper-3.4.9/data/myid
建立配置文件
能夠複製 zoo_sample.cfg 到 zoo.cfg 如下爲配置文件的參數設置:
# The number of milliseconds of each tick tickTime=2000 # The number of ticks that the initial # synchronization phase can take initLimit=10 # The number of ticks that can pass between # sending a request and getting an acknowledgement syncLimit=5 # the directory where the snapshot is stored. # do not use /tmp for storage, /tmp here is just # example sakes. dataDir=/u01/zookeeper/zookeeper-3.4.9/data # the port at which the clients will connect clientPort=2181 # the maximum number of client connections. # increase this if you need to handle more clients #maxClientCnxns=60 server.11=192.168.1.21:2888:3888 server.12=192.168.1.22:2888:3888 server.13=192.168.1.23:2888:3888
改好配置文件後,同步到集羣內的全部節點。
經常使用配置參數解析:
dataLogdDir=/path1 # 指定事務日誌的存儲路徑,能夠和dataDir在不一樣設備,這意味着可使用一個日誌的專用磁盤,避免日誌IO和快照競爭。 dataDir=/path2 # 運行數據的存放路徑 tickTime=2000 # 這個時間是做爲Zookeeper服務器之間或客戶端與服務器之間維持心跳的時間間隔,每隔tickTime時間就會發送一個心跳;最小 的session過時時間爲2倍tickTime maxClientCnxns=0 # 最大的併發鏈接數限制,設置爲0或者不設置該參數,表示不進行鏈接數的限制。 minSessionTimeout # 最小的會話超時時間,默認值 minSession=2*tickTime maxSessionTimeout # 最大的會話超時時間,默認值 maxSession=20*tickTime initLimit=10 # 此配置表示,容許follower(相對於Leaderer言的「客戶端」)鏈接並同步到Leader的初始化鏈接時間,以tickTime爲單位。當初始化鏈接時間超過該值,則表示鏈接失敗。 syncLimit=5 # 此配置項表示Leader與Follower之間發送消息時,請求和應答時間長度。若是follower在設置時間內不能與leader通訊,那麼此follower將會被丟棄。 # 集羣模式最關鍵的配置參數 server.11=192.168.1.21:2888:3888 # server.myid=ip:leader_port:inner_port # myid 爲服務器編號,用於標識服務器,這個值必須和dataDir目錄下myid文件中的值保證一致 # ip 爲當前服務器IP, # leader_port Leader的端口 # inner_port zk服務器之間內部通訊端口 # 同一個集羣內的服務器,須要把該集羣內的服務器列表信息都寫在配置文件中。
啓動服務 & 查看節點的角色分配狀況
# 192.168.1.21 bin/zkServer.sh start bin/zkServer.sh status # ZooKeeper JMX enabled by default # Using config: /u01/zookeeper/zookeeper-3.4.9/bin/../conf/zoo.cfg # Mode: leader # 192.168.1.22 bin/zkServer.sh start bin/zkServer.sh status # ZooKeeper JMX enabled by default # Using config: /u01/zookeeper/zookeeper-3.4.9/bin/../conf/zoo.cfg # Mode: follower # 192.168.1.23 bin/zkServer.sh start bin/zkServer.sh status # ZooKeeper JMX enabled by default # Using config: /u01/zookeeper/zookeeper-3.4.9/bin/../conf/zoo.cfg # Mode: follower
因而可知,集羣已經正常運行;
6、ZooKeeper的四字命令
客戶端能夠經過nc或telnet鏈接ZooKeeper Server提交指令
簡單用例:
# 檢查服務器狀態是否正常 echo ruok | nc localhost 2181 imok # 輸出服務器配置信息 echo conf | nc localhost 2181 clientPort=2181 dataDir=/u01/zookeeper/zookeeper-3.4.9/data/version-2 dataLogDir=/u01/zookeeper/zookeeper-3.4.9/data/version-2 tickTime=2000 maxClientCnxns=60 minSessionTimeout=4000 maxSessionTimeout=40000 serverId=11 initLimit=10 syncLimit=5 electionAlg=3 electionPort=3888 quorumPort=2888 peerType=0 # 輸出服務器狀態信息 echo stat | nc localhost 2181 Zookeeper version: 3.4.9-1757313, built on 08/23/2016 06:50 GMT Clients: /127.0.0.1:60822[0](queued=0,recved=1,sent=0) Latency min/avg/max: 0/1/1591 Received: 200338 Sent: 200389 Connections: 1 Outstanding: 0 Zxid: 0x200498db5 Mode: follower Node count: 166
7、ZooKeeper Client 簡單操做
9個基本操做指令:
簡單用例:
# 鏈接 ZooKeeper 服務器 bin/zkCli.sh -server localhost:2181 # 查看根下有哪些節點 [zk: localhost:2181(CONNECTED) 1] ls / [controller_epoch, controller, brokers, zookeeper, admin, isr_change_notification, consumers, config] # 查看 brokers 下有哪些子節點 [zk: localhost:2181(CONNECTED) 4] ls /brokers [ids, topics, seqid] # 在根下建立一個 "tuchao" 節點,並設置數據爲 "hello zookeeper" [zk: localhost:2181(CONNECTED) 5] create /tuchao "hello zookeeper" # 查看是否建立成功 [zk: localhost:2181(CONNECTED) 6] ls / [controller_epoch, controller, brokers, zookeeper, tuchao, admin, isr_change_notification, consumers, config] # 查看 /tuchao 中的數據 [zk: localhost:2181(CONNECTED) 7] get /tuchao hello zookeeper cZxid = 0x20049ab24 ctime = Sun Oct 09 15:45:02 CST 2016 mZxid = 0x20049ab24 mtime = Sun Oct 09 15:45:02 CST 2016 pZxid = 0x20049ab24 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 15 numChildren = 0 # 能夠看到剛剛設置的數據。 # 修改 /tuchao 中的數據爲 "Happy birthday" [zk: localhost:2181(CONNECTED) 8] set /tuchao "Happy birthday" cZxid = 0x20049ab24 ctime = Sun Oct 09 15:45:02 CST 2016 mZxid = 0x20049b2cc mtime = Sun Oct 09 15:51:17 CST 2016 pZxid = 0x20049ab24 cversion = 0 dataVersion = 1 # 能夠發現,當數據變動時,數據版本號增長了。 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 14 numChildren = 0 # 再查看一次 /tuchao 中的數據 [zk: localhost:2181(CONNECTED) 9] get /tuchao Happy birthday cZxid = 0x20049ab24 ctime = Sun Oct 09 15:45:02 CST 2016 mZxid = 0x20049b2cc mtime = Sun Oct 09 15:51:17 CST 2016 pZxid = 0x20049ab24 cversion = 0 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 14 numChildren = 0 # 給 /tuchao 建立一個子節點 /tuchao/abc1 [zk: localhost:2181(CONNECTED) 10] create /tuchao/abc1 "abc1 node" Created /tuchao/abc1 [zk: localhost:2181(CONNECTED) 11] ls /tuchao [abc1] # 刪除節點 /tuchao/abc1 [zk: localhost:2181(CONNECTED) 0] delete /tuchao/abc1 [zk: localhost:2181(CONNECTED) 1] ls /tuchao [] # 查看命令幫助,輸入 h [zk: localhost:2181(CONNECTED) 2] h ZooKeeper -server host:port cmd args stat path [watch] set path data [version] ls path [watch] delquota [-n|-b] path ls2 path [watch] setAcl path acl setquota -n|-b val path history redo cmdno printwatches on|off delete path [version] sync path listquota path rmr path get path [watch] create [-s] [-e] path data acl addauth scheme auth quit getAcl path close connect host:port
參考文獻:http://www.cnblogs.com/sunddenly/p/4033574.html