zookeeper介紹
什么是zookeeper捉邢?
zookpeeper是一個(gè)高可用的分布式管理與協(xié)調(diào)框架,基于ZAB算法也就是原子消息廣播協(xié)議的實(shí)現(xiàn)吮螺。它能夠很好的保證分布式環(huán)境中數(shù)據(jù)的一致性饶囚。也正是基于這樣的特性,使得它成為了解決分布式一致性問題的利器规脸。 它暴露了一些公共服務(wù)坯约,比如配置維護(hù)、域名服務(wù)莫鸭、分布式同步闹丐、組服務(wù)。我們可以使用zookeeper來實(shí)現(xiàn)比如集群管理被因、選舉卿拴、分布式鎖、分布式隊(duì)列等功能梨与。
zookeeper在hadoop生態(tài)系統(tǒng)中的地位:
zookeeper的特性:
- 順序一致性堕花,從一個(gè)客戶端發(fā)起的事務(wù)請(qǐng)求最終將會(huì)嚴(yán)格地按照其發(fā)起的順序被應(yīng)用到zookeeper中去。
- 原子性粥鞋,所有事務(wù)請(qǐng)求的處理結(jié)果在整個(gè)集群中所有機(jī)器上的應(yīng)用情況是一致的缘挽。也就是說要么整個(gè)集群所有的機(jī)器都成功應(yīng)用了某一事務(wù)。要么全部都沒有應(yīng)用,一定不會(huì)出現(xiàn)部分機(jī)器應(yīng)用了該事務(wù)壕曼,而另一部分沒有應(yīng)用的情況苏研。
- 單一視圖,無論客戶端連接的是哪一個(gè)zookeeper服務(wù)器腮郊。其看到的服務(wù)器端數(shù)據(jù)模型都是一致的摹蘑。
- 可靠性,一旦服務(wù)器成功地應(yīng)用了一個(gè)事務(wù)并完成了對(duì)客戶端的響應(yīng)轧飞。那么該事務(wù)所引起的服務(wù)器端狀態(tài)將會(huì)被一直保留下來衅鹿。除非有另外一個(gè)事務(wù)對(duì)其更改。
- 實(shí)時(shí)性过咬,通常所說的實(shí)時(shí)性大渤,就是指一旦事務(wù)被成功應(yīng)用。那么客戶端就能立即從服務(wù)器上獲取變更后的新數(shù)據(jù)援奢。zookeeper僅僅能保證在一段時(shí)間內(nèi)客戶端最終一定能從服務(wù)器端讀取最新的數(shù)據(jù)狀態(tài)兼犯。
zookeeper設(shè)計(jì)目標(biāo)
- 目標(biāo)1:簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu)。zookeeper就是以簡(jiǎn)單的樹形結(jié)構(gòu)來進(jìn)行相互協(xié)調(diào)的集漾。
- 目標(biāo)2:可以構(gòu)建集群切黔。一般 zookeeper集群通常由一組機(jī)器構(gòu)成,一般3-5臺(tái)機(jī)器就可以組成一個(gè) zookeeper集群了。只要集群中超過半數(shù)以上的機(jī)器能夠正常工作,那么整個(gè)集群就能夠正常對(duì)外提供服務(wù)具篇。
- 目標(biāo)3:順序訪問纬霞。對(duì)于來自每戶端的每一個(gè)請(qǐng)求,zookeeper都會(huì)分配一個(gè)全局唯一的遞增編號(hào),這個(gè)編號(hào)反應(yīng)了所有事務(wù)操作的先后順序。應(yīng)用程序可以使用 zookeeper的這個(gè)特性來實(shí)現(xiàn)更高層次的同步驱显。
- 目標(biāo)4:高性能诗芜。由于 zookeeper將全量數(shù)據(jù)存儲(chǔ)在內(nèi)存中,并直接服務(wù)于所有的非事務(wù)請(qǐng)求,因此尤其是在讀操作為主的場(chǎng)景下性能非常突出。在JMater壓力測(cè)試下(100%讀請(qǐng)求場(chǎng)景下),其結(jié)果大約在12~13W的QPS埃疫。
ZooKeeper的體系結(jié)構(gòu)
ZooKeeper 所有組件:
領(lǐng)導(dǎo)者(leader)伏恐,負(fù)責(zé)進(jìn)行投票的發(fā)起和決議,更新系統(tǒng)狀態(tài)
學(xué)習(xí)者(learner)栓霜,包括跟隨者(follower)和觀察者(observer)翠桦,follower用于接受客戶端請(qǐng)求并想客戶端返回結(jié)果,在選主過程中參與投票O(jiān)bserver可以接受客戶端連接胳蛮,將寫請(qǐng)求轉(zhuǎn)發(fā)給leader销凑,但observer不參加投票過程,只同步leader的狀態(tài)仅炊,observer的目的是為了擴(kuò)展系統(tǒng)斗幼,提高讀取速度
客戶端(client),請(qǐng)求發(fā)起方抚垄,也就是我們自己的java程序
zookeeper的數(shù)據(jù)結(jié)構(gòu)
ZooKeeper會(huì)維護(hù)一個(gè)具有層次關(guān)系的數(shù)據(jù)結(jié)構(gòu),非常類似于一個(gè)標(biāo)準(zhǔn)的文件系統(tǒng),如下圖所示:
ZooKeeper這種數(shù)據(jù)結(jié)構(gòu)有如下這些特點(diǎn):
- 每個(gè)子目錄項(xiàng)如NameService都被稱作znode,這個(gè)znode是被它所在的路徑唯一標(biāo)識(shí),如Server1這個(gè)znode的標(biāo)識(shí)為/NameService/Server1
- znode可以有子節(jié)點(diǎn)目錄,并且每個(gè)znode可以存儲(chǔ)數(shù)據(jù),注意EPHEMERAL類型的目錄節(jié)點(diǎn)不能有子節(jié)點(diǎn)目錄
- znode是有版本的,每個(gè)znode中存儲(chǔ)的數(shù)據(jù)可以有多個(gè)版本,也就是一個(gè)訪問路徑中可以存儲(chǔ)多份數(shù)據(jù)
- znode可以是臨時(shí)節(jié)點(diǎn),一旦創(chuàng)建這個(gè)znode的客戶端與服務(wù)器失去聯(lián)系,這個(gè)znode也將自動(dòng)刪除,ZooKeeper的客戶端和服務(wù)器通信采用長(zhǎng)連接方式,每個(gè)客戶端和服務(wù)器通過心跳來保持連接,這個(gè)連接狀態(tài)成為session,如果znode是臨時(shí)節(jié)點(diǎn),這個(gè)session失效,znode也就被刪除.
- znode的目錄名可以自動(dòng)編號(hào),如App1已經(jīng)存在,再創(chuàng)建的話,將會(huì)自動(dòng)命名為App2.
- znode可以被監(jiān)控,包括這個(gè)目錄節(jié)點(diǎn)中存儲(chǔ)的數(shù)據(jù)被修改,子節(jié)點(diǎn)目錄的變化等,一旦變化可以通知設(shè)置監(jiān)控的客戶端,這個(gè)是ZooKeeper的核心特性.
ZooKeeper的典型應(yīng)用場(chǎng)景
Zookeeper從設(shè)計(jì)模式角度來看,是一個(gè)基于觀察者模式設(shè)計(jì)的分布式服務(wù)管理框架,它負(fù)責(zé)存儲(chǔ)和管理大家都關(guān)心的數(shù)據(jù),然后接受觀察者的注冊(cè)蜕窿,一旦這些數(shù)據(jù)的狀態(tài)發(fā)生變化谋逻,Zookeeper就將負(fù)責(zé)通知已經(jīng)在Zookeeper上注冊(cè)的那些觀察者做出相應(yīng)的反應(yīng),從而實(shí)現(xiàn)集群中類似:Master/Slave管理模式、配置管理渠羞、集群管理斤贰、發(fā)布與訂閱、數(shù)據(jù)庫切換次询、分布式日志的收集、分布式環(huán)境瓷叫、隊(duì)列管理等等
- 配置管理:配置的管理在分布式應(yīng)用環(huán)境中很常見,比如我們?cè)谄匠5膽?yīng)用系統(tǒng)
中經(jīng)常會(huì)碰到這樣的需求:如機(jī)器的配置列表屯吊、運(yùn)行時(shí)的開關(guān)配置、數(shù)據(jù)庫配置信
息等摹菠。這些全局配置信息通常具備以下3個(gè)特性
1.數(shù)據(jù)量比較小
2.數(shù)據(jù)內(nèi)容在運(yùn)行時(shí)動(dòng)態(tài)發(fā)生變化
3.集群中各個(gè)節(jié)點(diǎn)共享信息,配置一致 - 集群管理: Zookeeper不僅能夠幫你維護(hù)當(dāng)前的集群中機(jī)器的服務(wù)狀態(tài),而且能夠幫你選出一個(gè)“總管”,讓這個(gè)總管來管理集群,這就是 Zookeeper的另一個(gè)功能Leader,它能實(shí)現(xiàn)集群容錯(cuò)功能
1.知道當(dāng)前集群中究竟有多少機(jī)器工作
2.對(duì)集群中每臺(tái)機(jī)器的運(yùn)行時(shí)狀態(tài)進(jìn)行數(shù)據(jù)收集
3.對(duì)集群中每臺(tái)機(jī)器進(jìn)行上下線操作 - 數(shù)據(jù)庫切換:比如我們初始化zookeeper的時(shí)候讀取其節(jié)點(diǎn)上的數(shù)據(jù)庫配置文件,當(dāng)配置發(fā)生變更時(shí)盒卸,zookeeper就能幫助我們把變更的通知發(fā)送到各個(gè)客戶端,每個(gè)客戶端在收到這個(gè)通知的時(shí)候就可以重新獲取最新的數(shù)據(jù)
- 分布式日志收集:我們可以做一個(gè)日志系統(tǒng)收集集群中所有的日志信息,進(jìn)行統(tǒng)一管理
- zookeeper的特性就是在分布式場(chǎng)景下高可用但是原生的API實(shí)現(xiàn)分布式功能非常困難,團(tuán)隊(duì)去實(shí)現(xiàn)太浪費(fèi)時(shí)間,即使實(shí)現(xiàn)了也未必穩(wěn)定那么可以采用第三方的客戶端的完美實(shí)現(xiàn),比如Apache的頂級(jí)項(xiàng)目 Curator框架次氨。
Zookeeper選舉
在zookeeper的選舉過程中蔽介,為了保證選舉過程最后能選出leader,就一定不能出現(xiàn)兩臺(tái)機(jī)器得票相同的僵局煮寡,所以一般的虹蓄,要求zk集群的server數(shù)量一定要是奇數(shù),也就是2n+1臺(tái)幸撕,并且薇组,如果集群出現(xiàn)問題,其中存活的機(jī)器必須大于n+1臺(tái)坐儿,否則leader無法獲得多數(shù)server的支持律胀,系統(tǒng)就自動(dòng)掛掉。所以一般是3個(gè)或者5個(gè)或者7個(gè)節(jié)點(diǎn)以此類推貌矿。
三臺(tái)主機(jī)的選舉過程:
A提案說炭菌,我要選自己,B你同意嗎逛漫?C你同意嗎黑低?B說,我同意選A尽楔;C說投储,我同意選A。(注意阔馋,這里超過半數(shù)了玛荞,其實(shí)在現(xiàn)實(shí)世界選舉已經(jīng)成功了。但是計(jì)算機(jī)世界是很嚴(yán)格呕寝,另外要理解算法勋眯,要繼續(xù)模擬下去。 接著B提案說,我要選自己客蹋,A你同意嗎塞蹭;A說,我已經(jīng)超半數(shù)同意當(dāng)選讶坯,你的提案無效番电;C說,A已經(jīng)超半數(shù)同意當(dāng)選辆琅,B提案無效漱办。接著C提案說,我要選自己婉烟,A你同意嗎娩井;A說,我已經(jīng)超半數(shù)同意當(dāng)選似袁,你的提案無效洞辣;B說,A已經(jīng)超半數(shù)同意當(dāng)選昙衅,C的提案無效扬霜。選舉已經(jīng)產(chǎn)生了Leader,后面的都是follower绒尊,只能服從Leader的命令畜挥。而且這里還有個(gè)小細(xì)節(jié),就是其實(shí)誰先啟動(dòng)誰當(dāng)頭婴谱。
Zookeeper安裝配置
1蟹但、結(jié)構(gòu):一共三個(gè)節(jié)點(diǎn)(zk服務(wù)器集群規(guī)模不小于3個(gè)節(jié)點(diǎn)),要求服務(wù)器之間系統(tǒng)時(shí)間保持一致。
2谭羔、上傳zk
進(jìn)行解壓:tar -zxvf zookeeper-3.4.5.tar.gz
重命名:mv zookeeper-3.4.5 zookeeper1
修改環(huán)境變量:vim /etc/profile
export ZOOKEEPER_HOME=/usr/local/zookeeper1
export PATH=.:$ZOOKEEPER_HOME/bin:$JAVA_HOME/...
刷新環(huán)境變量: source /etc/profile
到zookeeper下修改配置文件
cd /usr/local/zookeeper1/conf
mv zoo_sample.cfg zoo.cfg
修改conf: vim zoo.cfg 修改兩處
(1)dataDir=/usr/local/zookeeper1/data
(2)最后面添加
server.1=127.0.0.1:20881:30881
server.2=127.0.0.1:20882:30882
server.3=127.0.0.1:20883:30883
服務(wù)器標(biāo)識(shí)配置:
創(chuàng)建文件夾:mkdir data
創(chuàng)建文件myid并填寫內(nèi)容為1:vi myid (內(nèi)容為服務(wù)器標(biāo)識(shí) : 1)
進(jìn)行復(fù)制zookeeper1目錄到zookeeper2和zookeeper3
還有/etc/profile文件
把zookeeper2华糖、zookeeper3中的myid文件里的值修改為2和3
啟動(dòng)zookeeper:
路徑:/usr/local/zookeeper1/bin
執(zhí)行:zkServer.sh start
(注意這里3臺(tái)機(jī)器都要進(jìn)行啟動(dòng))
狀態(tài):zkServer.sh status(在三個(gè)節(jié)點(diǎn)上檢驗(yàn)zk的mode,一個(gè)leader和兩個(gè)follower)
zoo.cfg詳解:
tickTime: 基本事件單元,以毫秒為單位瘟裸。這個(gè)時(shí)間是作為 Zookeeper 服務(wù)器之間或客戶端與服務(wù)器之間維持心跳的時(shí)間間隔客叉,也就是每隔 tickTime時(shí)間就會(huì)發(fā)送一個(gè)心跳。默認(rèn)2000毫秒
*dataDir:存儲(chǔ)內(nèi)存中數(shù)據(jù)庫快照的位置话告,顧名思義就是 Zookeeper 保存數(shù)據(jù)的目錄兼搏,默認(rèn)情況下,Zookeeper將寫數(shù)據(jù)的日志文件也保存在這個(gè)目錄里沙郭。
clientPort: 這個(gè)端口就是客戶端連接 Zookeeper 服務(wù)器的端口佛呻,Zookeeper會(huì)監(jiān)聽這個(gè)端口,接受客戶端的訪問請(qǐng)求病线。
initLimit:這個(gè)配置項(xiàng)是用來配置 Zookeeper接受客戶端初始化連接時(shí)最長(zhǎng)能忍受多少個(gè)心跳時(shí)間間隔數(shù)吓著,當(dāng)已經(jīng)超過 10 個(gè)心跳的時(shí)間(也就是 tickTime)長(zhǎng)度后 Zookeeper 服務(wù)器還沒有收到客戶端的返回信息鲤嫡,那么表明這個(gè)客戶端連接失敗“筝海總的時(shí)間長(zhǎng)度就是 10*2000=20 秒暖眼。
syncLimit:這個(gè)配置項(xiàng)標(biāo)識(shí) Leader 與 Follower之間發(fā)送消息,請(qǐng)求和應(yīng)答時(shí)間長(zhǎng)度纺裁,最長(zhǎng)不能超過多少個(gè) tickTime 的時(shí)間長(zhǎng)度诫肠,總的時(shí)間長(zhǎng)度就是 5*2000=10 秒
server.A = B:C:D : A表示這個(gè)是第幾號(hào)服務(wù)器, B 是這個(gè)服務(wù)器的 ip 地址;C 表示的是這個(gè)服務(wù)器與集群中的 Leader 服務(wù)器交換信息的端口对扶;D 表示的是萬一集群中的 Leader 服務(wù)器掛了区赵,需要一個(gè)端口來重新進(jìn)行選舉,選出一個(gè)新的 Leader
Zookeeper CLI
ZooKeeper 命令行界面(CLI)是用來與 ZooKeeper 集成作開發(fā)進(jìn)行交互的浪南。這是在調(diào)試和使用不同的選項(xiàng)時(shí)的工作有用。
為了執(zhí)行ZooKeeper的CLI操作漱受, ZooKeeper服務(wù)器首先要啟動(dòng) (“bin/zkServer.sh start”) , 然后使用 ZooKeeper 客戶端 (“bin/zkCli.sh”). 當(dāng)客戶端啟動(dòng)后络凿,可以執(zhí)行以下操作 -
創(chuàng)建Znode
由一個(gè)給定的路徑來創(chuàng)建znode。flag參數(shù)指定了創(chuàng)建的 znode 是否為短暫的昂羡,持久的絮记,或連續(xù)的。默認(rèn)情況下虐先,所有的 znodes是持久的怨愤。
短暫 znode(flag: e)當(dāng)會(huì)話過期或當(dāng)客戶端斷開連接將被自動(dòng)刪除。
連續(xù) znode 保證 znode 路徑是唯一的蛹批。
語法:create /path data
要?jiǎng)?chuàng)建一個(gè)連續(xù)znode撰洗,如下圖所示添加 -s 標(biāo)志。
語法:create -s /path data
要?jiǎng)?chuàng)建一個(gè)臨時(shí)Znode腐芍,添加-e標(biāo)志差导,如下圖所示。
語法:create -e /path data
記住猪勇,當(dāng)丟失一個(gè)客戶端連接设褐,在臨時(shí) znode 將被刪除∑玻可以通過退出 ZooKeeper CLI 嘗試助析,然后重新打開命令行。獲取數(shù)據(jù)
它返回 znode 的相關(guān)數(shù)據(jù)和指定 znode 元數(shù)據(jù)椅您。這里將得到信息外冀,例如當(dāng)數(shù)據(jù)最后一次修改,在那里它被修改和有關(guān)數(shù)據(jù)的信息襟沮。此外 CLI 還用于分配監(jiān)視顯示通知有關(guān)的數(shù)據(jù)锥惋。
語法:get /path設(shè)置數(shù)據(jù)
設(shè)置指定znode的數(shù)據(jù)昌腰。當(dāng)你完成設(shè)置操作,就可以使用get CLI命令檢查數(shù)據(jù)膀跌。
語法
set /path data創(chuàng)建子znode
創(chuàng)建子znode類似于創(chuàng)建新的znodes遭商。唯一的區(qū)別在于,子 znode 的路徑將包含有父路徑捅伤。
語法:create /parent/path/subnode/path data列出子znode
該命令用于列出和顯示子 znode 劫流。
語法:ls /path檢查狀態(tài)
狀態(tài)描述了指定znode的元數(shù)據(jù)。它包含詳細(xì)信息丛忆,如時(shí)間戳祠汇,版本號(hào),訪問控制列表熄诡,數(shù)據(jù)長(zhǎng)度和子znode可很。
語法:stat /path刪除Znode
刪除指定znode和遞歸刪除所有的子znode。這只有在znode可用時(shí)發(fā)生凰浮。
語法:rmr /path
刪除(刪除/路徑)命令類似remove命令我抠,但它僅適用于無子znode的znode。
語法:delete /path
Zookeeper API
ZooKeeper有一個(gè)Java和C綁定的官方API袜茧。ZooKeeper社區(qū)提供了對(duì)于大多數(shù)語言(.NET菜拓,Python等)的非官方API。使用ZooKeeper的API笛厦,應(yīng)用程序可以連接纳鼎,互動(dòng),操作數(shù)據(jù)裳凸,協(xié)調(diào)贱鄙,以及從ZooKeeper集成斷開。
ZooKeeper API有一組豐富的功能登舞,在一個(gè)簡(jiǎn)單而安全的方式在ZooKeeper集成獲得所有功能贰逾。ZooKeeper API提供同步和異步方法。
ZooKeeper的集成和ZooKeeper API 在各個(gè)方面完全互補(bǔ)菠秒,它有利于開發(fā)商在一個(gè)簡(jiǎn)便的方式疙剑。 在本章討論Java綁定。
ZooKeeper的API基礎(chǔ)知識(shí)
應(yīng)用程序使用 ZooKeeper 集成的交互稱為 ZooKeeper 客戶端践叠。
Znode 是 ZooKeeper 集成的核心組件言缤,ZooKeeper API提供一個(gè)方法來處理znode所有使用ZooKeeper 集成。
客戶端應(yīng)遵循下面給出帶 ZooKeeper 集成一個(gè)清晰的交互步驟禁灼。
連接到ZooKeeper 管挟。ZooKeeper 集成分配客戶端的會(huì)話ID。
定期發(fā)送心跳到服務(wù)器弄捕。否則僻孝,ZooKeeper 集成過期的會(huì)話ID导帝,那么客戶端需要重新連接。
獲得/設(shè)置只要znodes會(huì)話ID是活動(dòng)的穿铆。
從 ZooKeeper 集成斷開您单,當(dāng)所有的任務(wù)都完成后。如果客戶端處于非活動(dòng)狀態(tài)較長(zhǎng)時(shí)間荞雏,那么 ZooKeeper 集成會(huì)自動(dòng)斷開客戶機(jī)虐秦。
Java代碼
ZooKeeper API的中心部分是ZooKeeper 類。它提供了一些選項(xiàng)來連接 ZooKeeper 集成在其構(gòu)造凤优,有以下幾種方法
connect ? 連接到 ZooKeeper 的集成
create ? 創(chuàng)建一個(gè) znode
exists ? 檢查znode是否存在及其信息
getData ? 從一個(gè)特定的znode獲取數(shù)據(jù)
setData ? 設(shè)置數(shù)據(jù)在特定znode
getChildren ? 得到一個(gè)特定 znode 的所有可用子節(jié)點(diǎn)
delete ? 刪除一個(gè)特定的 znode 及其所有子節(jié)點(diǎn)
close ? 關(guān)閉連接
連接到 ZooKeeper 集合
ZooKeeper類通過它的構(gòu)造函數(shù)提供了連接功能悦陋。構(gòu)造函數(shù)的簽名如下:
ZooKeeper(String connectionString, int sessionTimeout, Watcher watcher)
在這里,
connectionString ? ZooKeeper集合主機(jī)。
sessionTimeout ? 以毫秒為單位會(huì)話超時(shí)筑辨。
watcher ? 一個(gè)執(zhí)行對(duì)象“觀察者”的接口俺驶。ZooKeeper 集合返回通過監(jiān)控器對(duì)象的連接狀態(tài)。