一 Zookeeper概述
1.1 概述
Zookeeper是一個(gè)開源的分布式的,為分布式應(yīng)用提供協(xié)調(diào)服務(wù)的Apache項(xiàng)目踊跟。
Zookeeper從設(shè)計(jì)模式角度來理解:是一個(gè)基于觀察者模式設(shè)計(jì)的分布式服務(wù)管理框架款青,它負(fù)責(zé)存儲和管理大家都關(guān)心的數(shù)據(jù)锹淌,然后接受觀察者的注冊,一旦這些數(shù)據(jù)的狀態(tài)發(fā)生變化骨宠,Zookeeper就將負(fù)責(zé)通知已經(jīng)在Zookeeper上注冊的那些觀察者做出相應(yīng)的反應(yīng)米罚,從而實(shí)現(xiàn)集群中類似Master/Slave管理模式
Zookeeper=文件系統(tǒng)+通知機(jī)制
1.2 特點(diǎn)
1)Zookeeper:一個(gè)領(lǐng)導(dǎo)者(leader)钧汹,多個(gè)跟隨者(follower)組成的集群。
2)Leader負(fù)責(zé)進(jìn)行投票的發(fā)起和決議录择,更新系統(tǒng)狀態(tài)
3)Follower用于接收客戶請求并向客戶端返回結(jié)果拔莱,在選舉Leader過程中參與投票
4)集群中只要有半數(shù)以上節(jié)點(diǎn)存活,Zookeeper集群就能正常服務(wù)糊肠。
5)全局?jǐn)?shù)據(jù)一致:每個(gè)server保存一份相同的數(shù)據(jù)副本辨宠,client無論連接到哪個(gè)server,數(shù)據(jù)都是一致的货裹。
6)更新請求順序進(jìn)行,來自同一個(gè)client的更新請求按其發(fā)送順序依次執(zhí)行精偿。
7)數(shù)據(jù)更新原子性弧圆,一次數(shù)據(jù)更新要么成功,要么失敗笔咽。
8)實(shí)時(shí)性搔预,在一定時(shí)間范圍內(nèi),client能讀到最新數(shù)據(jù)叶组。
1.3 數(shù)據(jù)結(jié)構(gòu)
ZooKeeper數(shù)據(jù)模型的結(jié)構(gòu)與Unix文件系統(tǒng)很類似拯田,整體上可以看作是一棵樹,每個(gè)節(jié)點(diǎn)稱做一個(gè)ZNode甩十。
?很顯然zookeeper集群自身維護(hù)了一套數(shù)據(jù)結(jié)構(gòu)船庇。這個(gè)存儲結(jié)構(gòu)是一個(gè)樹形結(jié)構(gòu),其上的每一個(gè)節(jié)點(diǎn)侣监,我們稱之為"znode"鸭轮,每一個(gè)znode默認(rèn)能夠存儲1MB的數(shù)據(jù),每個(gè)ZNode都可以通過其路徑唯一標(biāo)識
[if !vml]
[endif]
1.5 下載地址
1)官網(wǎng)首頁:
https://zookeeper.apache.org/
2)下載截圖
[if !vml]
[endif]
[if !vml]
[endif]
[if !vml]
[endif]
二 Zookeeper安裝
2.1 本地模式安裝部署
1)安裝前準(zhǔn)備:
(1)安裝jdk
(2)通過filezilla工具拷貝zookeeper到到linux系統(tǒng)下
(3)修改tar包權(quán)限
chmod u+x zookeeper-3.4.10.tar.gz
(4)解壓到指定目錄
[root@hadoop01 software]$ tar -zxvfzookeeper-3.4.10.tar.gz -C /home/app/hadoop/
app/
進(jìn)入到app查看
[if !vml]
[endif]
2)配置修改
將/home/app/hadoop/app/zookeeper-3.4.10/conf這個(gè)路徑下的zoo_sample.cfg修改為zoo.cfg橄霉;
?????????? 進(jìn)入zoo.cfg文件:vimzoo.cfg
??????????????????? 修改dataDir路徑為
dataDir=/home/app/hadoop/app/opt/module/zookeeper-3.4.10/zkData
?????????? 在/home/app/hadoop/app/zookeeper-3.4.10/這個(gè)目錄上創(chuàng)建zkData文件夾
??????????????????? mkdir zkData
3)操作zookeeper
(1)啟動zookeeper
[root@hadoop01zookeeper-3.4.10]$ bin/zkServer.sh start
(2)查看進(jìn)程是否啟動
???????? [root@hadoop01zookeeper-3.4.10]$ jps
4020Jps
4001QuorumPeerMain
(3)查看狀態(tài):
[root@hadoop01zookeeper-3.4.10]$ bin/zkServer.sh status
ZooKeeperJMX enabled by default
Usingconfig: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg
Mode:standalone
(4)啟動客戶端:
[root@hadoop01 zookeeper-3.4.10]$bin/zkCli.sh
(5)退出客戶端:
[zk: localhost:2181(CONNECTED) 0]
quit
(6)停止zookeeper
[root@hadoop01 zookeeper-3.4.10]$ bin/zkServer.sh stop
3.1 分布式安裝部署
0)集群規(guī)劃
在hadoop102窃爷、hadoop103和hadoop104三個(gè)節(jié)點(diǎn)上部署Zookeeper。
1)解壓安裝
(1)解壓zookeeper安裝包到/opt/module/目錄下
[atguigu@hadoop102 software]$
tar -zxvf
zookeeper-3.4.10.tar.gz -C/home/hadoop/app/
(2)在/opt/module/zookeeper-3.4.10/這個(gè)目錄下創(chuàng)建zkData
???????? mkdir-p zkData
(3)重命名/opt/module/zookeeper-3.4.10/conf這個(gè)目錄下的zoo_sample.cfg為zoo.cfg
???????? mvzoo_sample.cfg zoo.cfg
2)配置zoo.cfg文件
???????? (1)具體配置
???????? dataDir=/home/hadoop/app/zookeeper-3.4.10/zkData
???????? 增加如下配置
???????? #######################cluster##########################
server.2=hadoop101:2888:3888
server.3=hadoop1022888:3888
server.4=hadoop103:2888:3888
(2)配置參數(shù)解讀
Server.A=B:C:D。
A是一個(gè)數(shù)字按厘,表示這個(gè)是第幾號服務(wù)器医吊;
B是這個(gè)服務(wù)器的ip地址;
C是這個(gè)服務(wù)器與集群中的Leader服務(wù)器交換信息的端口逮京;
D是萬一集群中的Leader服務(wù)器掛了遮咖,需要一個(gè)端口來重新進(jìn)行選舉,選出一個(gè)新的Leader造虏,而這個(gè)端口就是用來執(zhí)行選舉時(shí)服務(wù)器相互通信的端口御吞。
集群模式下配置一個(gè)文件myid,這個(gè)文件在dataDir目錄下漓藕,這個(gè)文件里面有一個(gè)數(shù)據(jù)就是A的值陶珠,Zookeeper啟動時(shí)讀取此文件,拿到里面的數(shù)據(jù)與zoo.cfg里面的配置信息比較從而判斷到底是哪個(gè)server享钞。
3)集群操作
(1)在/home/hadoop/app/zookeeper-3.4.10/zkData目錄下創(chuàng)建一個(gè)myid的文件
???????? touchmyid
添加myid文件揍诽,注意一定要在linux里面創(chuàng)建,在notepad++里面很可能亂碼
(2)編輯myid文件
???????? vimyid
???????? 在文件中添加與server對應(yīng)的編號:如1
(3)拷貝配置好的zookeeper到其他機(jī)器上
???????? scp -r zookeeper-3.4.10/ hadoop02:/home/hadoop/app/
???????? scp -rzookeeper-3.4.10/ hadoop03:/home/hadoop/app/
server.1=192.168.216.114:2888:3888
server.2=192.168.216.115:2888:3888
server.3=192.168.216.116:2888:3888
server.4=192.168.216.117:2888:3888
server.5=192.168.216.118:2888:3888
???????? 并分別修改myid文件中內(nèi)容為2栗竖、3
(4)分別啟動zookeeper
???????? [root@hadoop001zookeeper-3.4.10]# bin/zkServer.sh start
[root@hadoop002 zookeeper-3.4.10]#bin/zkServer.sh start
[root@hadoop003 zookeeper-3.4.10]#bin/zkServer.sh start
(5)查看狀態(tài)
[root@hadoop001 zookeeper-3.4.10]#bin/zkServer.sh status
JMX enabled by default
Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg
Mode:follower
[root@hadoop002 zookeeper-3.4.10]# bin/zkServer.sh status
JMX enabled by default
Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg
Mode: leader
[root@hadoop003 zookeeper-3.4.5]# bin/zkServer.sh status
JMX enabled by default
Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg
Mode:follower
解讀zoo.cfg 文件中參數(shù)含義
1)tickTime:通信心跳數(shù)暑脆,Zookeeper服務(wù)器心跳時(shí)間,單位毫秒
Zookeeper使用的基本時(shí)間狐肢,服務(wù)器之間或客戶端與服務(wù)器之間維持心跳的時(shí)間間隔添吗,也就是每個(gè)tickTime時(shí)間就會發(fā)送一個(gè)心跳,時(shí)間單位為毫秒份名。
它用于心跳機(jī)制碟联,并且設(shè)置最小的session超時(shí)時(shí)間為兩倍心跳時(shí)間。(session的最小超時(shí)時(shí)間是2*tickTime)
2)initLimit:LF初始通信時(shí)限
集群中的follower跟隨者服務(wù)器(F)與leader領(lǐng)導(dǎo)者服務(wù)器(L)之間初始連接時(shí)能容忍的最多心跳數(shù)(tickTime的數(shù)量)僵腺,用它來限定集群中的Zookeeper服務(wù)器連接到Leader的時(shí)限鲤孵。
投票選舉新leader的初始化時(shí)間
Follower在啟動過程中,會從Leader同步所有最新數(shù)據(jù)辰如,然后確定自己能夠?qū)ν夥?wù)的起始狀態(tài)普监。
Leader允許F在initLimit時(shí)間內(nèi)完成這個(gè)工作。
3)syncLimit:LF同步通信時(shí)限
集群中Leader與Follower之間的最大響應(yīng)時(shí)間單位琉兜,假如響應(yīng)超過syncLimit * tickTime凯正,
Leader認(rèn)為Follwer死掉,從服務(wù)器列表中刪除Follwer呕童。
在運(yùn)行過程中漆际,Leader負(fù)責(zé)與ZK集群中所有機(jī)器進(jìn)行通信,例如通過一些心跳檢測機(jī)制夺饲,來檢測機(jī)器的存活狀態(tài)奸汇。
如果L發(fā)出心跳包在syncLimit之后施符,還沒有從F那收到響應(yīng),那么就認(rèn)為這個(gè)F已經(jīng)不在線了擂找。
4)dataDir:數(shù)據(jù)文件目錄+數(shù)據(jù)持久化路徑
保存內(nèi)存數(shù)據(jù)庫快照信息的位置戳吝,如果沒有其他說明,更新的事務(wù)日志也保存到數(shù)據(jù)庫贯涎。
5)clientPort:客戶端連接端口
監(jiān)聽客戶端連接的端口
3.2 監(jiān)聽器原理
[if !vml]
[endif]1)監(jiān)聽原理詳解:
1)首先要有一個(gè)main()線程
2)在main線程中創(chuàng)建Zookeeper客戶端听哭,這時(shí)就會創(chuàng)建兩個(gè)線程,一個(gè)負(fù)責(zé)網(wǎng)絡(luò)連接通信(connet)塘雳,一個(gè)負(fù)責(zé)監(jiān)聽(listener)陆盘。
3)通過connect線程將注冊的監(jiān)聽事件發(fā)送給Zookeeper。
4)在Zookeeper的注冊監(jiān)聽器列表中將注冊的監(jiān)聽事件添加到列表中败明。
5)Zookeeper監(jiān)聽到有數(shù)據(jù)或路徑變化隘马,就會將這個(gè)消息發(fā)送給listener線程。
6)listener線程內(nèi)部調(diào)用了process()方法妻顶。
2)常見的監(jiān)聽
(1)監(jiān)聽節(jié)點(diǎn)數(shù)據(jù)的變化:
get path [watch]
??? (2)監(jiān)聽子節(jié)點(diǎn)增減的變化
ls path [watch]
3.3 客戶端命令行操作
命令基本語法功能描述
help顯示所有操作命令
ls path [watch]使用 ls 命令來查看當(dāng)前znode中所包含的內(nèi)容
ls2 path [watch]查看當(dāng)前節(jié)點(diǎn)數(shù)據(jù)并能看到更新次數(shù)等數(shù)據(jù)
create普通創(chuàng)建
-s? 含有序列
-e? 臨時(shí)(重啟或者超時(shí)消失)
get path [watch]獲得節(jié)點(diǎn)的值
set設(shè)置節(jié)點(diǎn)的具體值
stat查看節(jié)點(diǎn)狀態(tài)
delete刪除節(jié)點(diǎn)
rmr遞歸刪除節(jié)點(diǎn)
1)啟動客戶端
[atguigu@hadoop103zookeeper-3.4.10]$ bin/zkCli.sh
2)顯示所有操作命令
[zk:localhost:2181(CONNECTED) 1] help
3)查看當(dāng)前znode中所包含的內(nèi)容
[zk:localhost:2181(CONNECTED) 0] ls /
[zookeeper]
4)查看當(dāng)前節(jié)點(diǎn)數(shù)據(jù)并能看到更新次數(shù)等數(shù)據(jù)
[zk:localhost:2181(CONNECTED) 1] ls2 /
[zookeeper]
cZxid = 0x0
ctime = Thu Jan01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan01 08:00:00 CST 1970
pZxid = 0x0
cversion = -1
dataVersion = 0
aclVersion = 0
ephemeralOwner =0x0
dataLength = 0
numChildren = 1
5)創(chuàng)建普通節(jié)點(diǎn)
[zk:localhost:2181(CONNECTED) 2] create /app1 "hello app1"
Created /app1
[zk:localhost:2181(CONNECTED) 4] create /app1/server101 "192.168.1.111"
Created /app1/server101
6)獲得節(jié)點(diǎn)的值
[zk:localhost:2181(CONNECTED) 6] get /app1
hello app1
cZxid =0x20000000a
ctime = Mon Jul17 16:08:35 CST 2017
mZxid =0x20000000a
mtime = Mon Jul17 16:08:35 CST 2017
pZxid =0x20000000b
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner =0x0
dataLength = 10
numChildren = 1
[zk:localhost:2181(CONNECTED) 8] get /app1/server101
192.168.1.101
cZxid =0x20000000b
ctime = Mon Jul17 16:11:04 CST 2017
mZxid =0x20000000b
mtime = Mon Jul17 16:11:04 CST 2017
pZxid =0x20000000b
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner =0x0
dataLength = 13
numChildren = 0
7)創(chuàng)建短暫節(jié)點(diǎn)
[zk:localhost:2181(CONNECTED) 9] create -e /app-emphemeral 8888
(1)在當(dāng)前客戶端是能查看到的
[zk: localhost:2181(CONNECTED) 10] ls /
[app1, app-emphemeral, zookeeper]
(2)退出當(dāng)前客戶端然后再重啟客戶端
???????? [zk: localhost:2181(CONNECTED) 12] quit
[atguigu@hadoop104zookeeper-3.4.10]$ bin/zkCli.sh
(3)再次查看根目錄下短暫節(jié)點(diǎn)已經(jīng)刪除
???????? [zk: localhost:2181(CONNECTED) 0] ls /
[app1,zookeeper]
8)創(chuàng)建帶序號的節(jié)點(diǎn)
??? (1)先創(chuàng)建一個(gè)普通的根節(jié)點(diǎn)app2
???????? [zk: localhost:2181(CONNECTED) 11]create /app2 "app2"
??? (2)創(chuàng)建帶序號的節(jié)點(diǎn)
???????? [zk: localhost:2181(CONNECTED) 13]create -s /app2/aa 888
Created /app2/aa0000000000
[zk: localhost:2181(CONNECTED) 14] create -s /app2/bb 888
Created /app2/bb0000000001
[zk:localhost:2181(CONNECTED) 15] create -s /app2/cc 888
Created /app2/cc0000000002
如果原節(jié)點(diǎn)下有1個(gè)節(jié)點(diǎn)酸员,則再排序時(shí)從1開始,以此類推讳嘱。
[zk:localhost:2181(CONNECTED) 16] create -s /app1/aa 888
Created/app1/aa0000000001
9)修改節(jié)點(diǎn)數(shù)據(jù)值
[zk:localhost:2181(CONNECTED) 2] set /app1 999
10)節(jié)點(diǎn)的值變化監(jiān)聽
??? (1)在104主機(jī)上注冊監(jiān)聽/app1節(jié)點(diǎn)數(shù)據(jù)變化
[zk:localhost:2181(CONNECTED) 26] get /app1 watch
??? (2)在103主機(jī)上修改/app1節(jié)點(diǎn)的數(shù)據(jù)
[zk:localhost:2181(CONNECTED) 5] set /app1?777
??? (3)觀察104主機(jī)收到數(shù)據(jù)變化的監(jiān)聽
WATCHER::
WatchedEventstate:SyncConnected type:NodeDataChanged path:/app1
11)節(jié)點(diǎn)的子節(jié)點(diǎn)變化監(jiān)聽(路徑變化)
??? (1)在104主機(jī)上注冊監(jiān)聽/app1節(jié)點(diǎn)的子節(jié)點(diǎn)變化
[zk:localhost:2181(CONNECTED) 1] ls /app1 watch
[aa0000000001,server101]
??? (2)在103主機(jī)/app1節(jié)點(diǎn)上創(chuàng)建子節(jié)點(diǎn)
[zk: localhost:2181(CONNECTED) 6] create /app1/bb 666
Created /app1/bb
??? (3)觀察104主機(jī)收到子節(jié)點(diǎn)變化的監(jiān)聽
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChangedpath:/app1
12)刪除節(jié)點(diǎn)
[zk: localhost:2181(CONNECTED) 4] delete /app1/bb
13)遞歸刪除節(jié)點(diǎn)
[zk: localhost:2181(CONNECTED) 7] rmr /app2
14)查看節(jié)點(diǎn)狀態(tài)
[zk: localhost:2181(CONNECTED) 12] stat /app1
cZxid = 0x20000000a
ctime = Mon Jul 17 16:08:35 CST 2017
mZxid = 0x200000018
mtime = Mon Jul 17 16:54:38 CST 2017
pZxid = 0x20000001c
cversion = 4
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 2