概念:
zookeeper是一個開源的基于Google chubby的分布式協(xié)調(diào)框架情臭,主要用于分布式數(shù)據(jù)一致性解決方案,zookeeper可以提供配置中心服務(wù)趴久、數(shù)據(jù)的發(fā)布和訂閱丸相、集群管理保證集群的數(shù)據(jù)強一致性、負載均衡彼棍、選舉灭忠、分布式鎖膳算、分布式隊列等功能。
zookeeper的特性:
- 順序性:客戶端發(fā)起的請求會按照嚴格的順序應用到zookeer中
- 原子性:所有的事務(wù)請求在集群的所有的機器處理的結(jié)果是一致的弛作,使整個集群的所有的機器要么都成功的應用了某一事務(wù)涕蜂,要么全部都沒有應用某一事務(wù)
- 可靠性:集群的機器器應用了某一數(shù)據(jù)并成功的響應了客戶端后,數(shù)據(jù)會在整個集群中同步的保存下來映琳,保證數(shù)據(jù)不丟失
- 數(shù)據(jù)一致性:一旦集群的服務(wù)器應用了某一事務(wù)后机隙,客戶端就能夠立即從服務(wù)器端讀取事務(wù)變更后的最新數(shù)據(jù)狀態(tài),zookeeper的實時性重點的之處在于只是在一定時間進行,允許分布式數(shù)據(jù)經(jīng)過一個時間窗口達到最終一致萨西,這個時間窗口也是差不多接近實時的有鹿。
zookeeper集群為何是奇數(shù)?
1谎脯、容錯:在容錯能力相同的情況下葱跋,奇數(shù)臺更節(jié)省資源。
由于在增刪改操作中需要半數(shù)以上服務(wù)器通過源梭,來分析以下情況娱俺。
2臺服務(wù)器,至少2臺正常運行才行(2的半數(shù)為1废麻,半數(shù)以上最少為2)荠卷,正常運行1臺服務(wù)器都不允許掛掉
3臺服務(wù)器,至少2臺正常運行才行(3的半數(shù)為1.5烛愧,半數(shù)以上最少為2)僵朗,正常運行可以允許1臺服務(wù)器掛掉
4臺服務(wù)器,至少3臺正常運行才行(4的半數(shù)為2屑彻,半數(shù)以上最少為3)验庙,正常運行可以允許1臺服務(wù)器掛掉
5臺服務(wù)器,至少3臺正常運行才行(5的半數(shù)為2.5社牲,半數(shù)以上最少為3)粪薛,正常運行可以允許2臺服務(wù)器掛掉
6臺服務(wù)器,至少3臺正常運行才行(6的半數(shù)為3搏恤,半數(shù)以上最少為4)违寿,正常運行可以允許2臺服務(wù)器掛掉
通過以上可以發(fā)現(xiàn),3臺服務(wù)器和4臺服務(wù)器都最多允許1臺服務(wù)器掛掉熟空,5臺服務(wù)器和6臺服務(wù)器都最多允許2臺服務(wù)器掛掉
但是明顯4臺服務(wù)器成本高于3臺服務(wù)器成本藤巢,6臺服務(wù)器成本高于5服務(wù)器成本。這是由于半數(shù)以上投票通過決定的息罗。
2掂咒、防止由腦裂造成的集群不可用。
首先,什么是腦裂绍刮?集群的腦裂通常是發(fā)生在節(jié)點之間通信不可達的情況下温圆,集群會分裂成不同的小集群,小集群各自選出自己的master節(jié)點孩革,導致原有的集群出現(xiàn)多個master節(jié)點的情況岁歉,這就是腦裂。
下面舉例說一下為什么采用奇數(shù)臺節(jié)點膝蜈,就可以防止由于腦裂造成的服務(wù)不可用:
(1) 假如zookeeper集群有 5 個節(jié)點锅移,發(fā)生了腦裂,腦裂成了A饱搏、B兩個小集群:
(a) A : 1個節(jié)點 非剃,B :4個節(jié)點
(b) A : 2個節(jié)點, B :3個節(jié)點
可以看出窍帝,上面這兩種情況下,A诽偷、B中總會有一個小集群滿足 可用節(jié)點數(shù)量 > 總節(jié)點數(shù)量/2 坤学。所以zookeeper集群仍然能夠選舉出leader , 仍然能對外提供服務(wù)报慕,只不過是有一部分節(jié)點失效了而已深浮。
(2) 假如zookeeper集群有4個節(jié)點,同樣發(fā)生腦裂眠冈,腦裂成了A飞苇、B兩個小集群:
(a) A:1個節(jié)點 , B:3個節(jié)點
(b) A:2個節(jié)點 蜗顽, B:2個節(jié)點
可以看出布卡,情況(a) 是滿足選舉條件的,與(1)中的例子相同雇盖。 但是情況(b) 就不同了忿等,因為A和B都是2個節(jié)點,都不滿足 可用節(jié)點數(shù)量 > 總節(jié)點數(shù)量/2 的選舉條件崔挖, 所以此時zookeeper就徹底不能提供服務(wù)了贸街。
綜合上面兩個例子可以看出: 在節(jié)點數(shù)量是奇數(shù)個的情況下, zookeeper集群總能對外提供服務(wù)狸相;如果節(jié)點數(shù)量是偶數(shù)個薛匪,會存在zookeeper集群不能用的可能性,腦裂成兩個均等的子集群的時候脓鹃。
在生產(chǎn)環(huán)境中逸尖,如果zookeeper集群不能提供服務(wù),那將是致命的 , 所以zookeeper集群的節(jié)點數(shù)一般采用奇數(shù)個冷溶。
最典型集群模式:Master/Slave 模式(主備模式)
Leader:負責進行投票的發(fā)起和決議渐白,分布式讀寫,更新請求轉(zhuǎn)發(fā)逞频;
Follower:負責接收客戶端請求并向客戶端返回結(jié)果纯衍,在選舉Leader過程中參與投票;
在這種模式中苗胀,通常 Master 服務(wù)器作為主服務(wù)器提供寫服務(wù)襟诸,其他的 Slave 服務(wù)器從服務(wù)器通過異步復制的方式獲取 Master 服務(wù)器最新的數(shù)據(jù)提供讀服務(wù)。
但是基协,在 ZooKeeper 中沒有選擇傳統(tǒng)的 Master/Slave 概念歌亲,而是引入了Leader、Follower 和 Observer 三種角色澜驮。
ZooKeeper 集群中的所有機器選舉過程來選定 Leader
Leader 既可以為客戶端提供寫服務(wù)又能提供讀服務(wù)陷揪。除了 Leader 外,F(xiàn)ollower 和 Observer 都只能提供讀服務(wù)杂穷。
observer的行為在大多數(shù)情況下與follower完全一致悍缠,F(xiàn)ollower 和 Observer 唯一的區(qū)別在于 Observer 機器不參與 Leader 的選舉過程,也不參與寫操作的“過半寫成功”策略耐量,他只接受讀請求飞蚓,將寫請求轉(zhuǎn)發(fā)給leader,因此 Observer 機器可以在不影響寫性能的情況下提升集群的讀性能廊蜒。
數(shù)據(jù)一致和分區(qū)容錯
ZAB 協(xié)議
ZAB(ZooKeeper Atomic Broadcast 原子廣播)協(xié)議是為分布式協(xié)調(diào)服務(wù) ZooKeeper 專門設(shè)計的一種支持崩潰恢復的原子廣播協(xié)議趴拧。
ZooKeeper 中,主要依賴 ZAB 協(xié)議來實現(xiàn)分布式數(shù)據(jù)一致性山叮,基于該協(xié)議著榴,ZooKeeper 實現(xiàn)了一種主備模式的系統(tǒng)架構(gòu)來保持集群中各個副本之間的數(shù)據(jù)一致性。
這里所說的主備系統(tǒng)架構(gòu)模型是指屁倔,在zookeeper集群中兄渺,只有一臺leader負責處理外部客戶端的事物請求(或?qū)懖僮?,然后leader服務(wù)器將客戶端的寫操作數(shù)據(jù)同步到所有的follower節(jié)點中汰现。
ZAB 協(xié)議包括兩種基本的模式挂谍,分別是崩潰恢復和消息廣播:
ZAB的協(xié)議核心是在整個zookeeper集群中只有一個節(jié)點即Leader將客戶端的寫操作轉(zhuǎn)化為事物(或提議proposal)。Leader節(jié)點再數(shù)據(jù)寫完之后瞎饲,將向所有的follower節(jié)點發(fā)送數(shù)據(jù)廣播請求(或數(shù)據(jù)復制)口叙,等待所有的follower節(jié)點反饋。在ZAB協(xié)議中嗅战,只要超過半數(shù)follower節(jié)點反饋OK妄田,Leader節(jié)點就會向所有的follower服務(wù)器發(fā)送commit消息俺亮。即將leader節(jié)點上的數(shù)據(jù)同步到follower節(jié)點之上。
當整個服務(wù)框架在啟動過程中疟呐,或是當Leader服務(wù)器出現(xiàn)網(wǎng)絡(luò)中斷崩潰退出與重啟等異常情況時脚曾,ZAB就會進入崩潰恢復模式并選舉產(chǎn)生新的Leader服務(wù)器。
當選舉產(chǎn)生了新的Leader服務(wù)器启具,同時集群中已經(jīng)有過半的機器與該Leader服務(wù)器完成了狀態(tài)同步之后本讥,ZAB協(xié)議就會退出崩潰恢復模式,進入消息廣播模式鲁冯。
當新的機器加入到集群中的時候拷沸,如果已經(jīng)存在leader服務(wù)器,那么新加入的服務(wù)器就會自覺進入崩潰恢復模式薯演,找到leader進行數(shù)據(jù)同步撞芍。
以上其實大致經(jīng)歷了三個步驟:
- 1.崩潰恢復:主要就是Leader選舉過程
- 2.數(shù)據(jù)同步:Leader服務(wù)器與其他服務(wù)器進行數(shù)據(jù)同步
- 3.消息廣播:Leader服務(wù)器將數(shù)據(jù)發(fā)送給其他服務(wù)器
消息廣播模式
ZAB協(xié)議的消息廣播過程使用的是一個原子廣播協(xié)議,類似二階段提交2PC跨扮。
一階段:發(fā)送Proposal序无,客戶端執(zhí)行事務(wù)
客戶端的請求時,而在第一階段衡创,Leader機器會將事物消息生成對應的Proposal進行廣播帝嗡,并且會生成一個單調(diào)遞增的ID,作為事物的ID(ZXID),由于ZAB協(xié)議需要保證事物嚴格的上下順序性钧汹,所以會嚴格按照ZXID的先后來處理對應的消息丈探。而在消息廣播發(fā)起后录择,Leader會為每一個Follower服務(wù)器分配一個單獨的隊列拔莱,然后將需要廣播出去的事物Proposal依次存放進這個FIFO的隊列中,每個Follower機器收到事物消息后隘竭,會按照事物日志的方式寫入塘秦,成功后反饋給Leader機器Ack響應。
二階段:半數(shù)提交事務(wù)
當收到半數(shù)以上的Ack響應后动看,Leader就會發(fā)起第二階段的Commit消息給所有的Follower機器尊剔,并且這個時候Leader也會和Follower一樣進行本地事物的提交操作,完成整個消息的傳遞和提交菱皆。
整個步驟如下:
- 客戶端發(fā)起一個寫操作請求
- Leader服務(wù)器將客戶端的request請求轉(zhuǎn)化為事物proposql提案须误,同時為每個proposal分配一個全局唯一的ID,即ZXID仇轻。
- leader服務(wù)器與每個follower之間都有一個隊列京痢,leader將消息發(fā)送到該隊列
- follower機器從隊列中取出消息處理完(寫入本地事物日志中)畢后,向leader服務(wù)器發(fā)送ACK確認篷店。
- leader服務(wù)器收到半數(shù)以上的follower的ACK后祭椰,即認為可以發(fā)送commit
- leader向所有的follower服務(wù)器發(fā)送commit消息臭家。
崩潰恢復:
崩潰恢復包括兩部分:Leader選舉和 數(shù)據(jù)恢復
ZAB協(xié)議崩潰恢復要求滿足如下2個要求:
- 確保已經(jīng)被leader提交的proposal必須最終被所有的follower服務(wù)器提交。
- 確保丟棄已經(jīng)被leader發(fā)出但是沒有被提交的proposal方淤。
根據(jù)上述要求钉赁,新選舉出來的leader不能包含未提交的proposal,即新選舉的leader必須都是已經(jīng)提交了的proposal的follower服務(wù)器節(jié)點携茂。同時你踩,新選舉的leader節(jié)點中含有最高的ZXID。這樣做的好處就是可以避免了leader服務(wù)器檢查proposal的提交和丟棄工作
ZXID
zxid邑蒋,也就是事務(wù)id姓蜂,為了保證事務(wù)的順序一致性,zookeeper采用了遞增的事務(wù)id號(zxid)來標識事務(wù)医吊。所有的提議(proposal)都在被提出的時候加上了zxid钱慢,實際中zxid是一個64位的數(shù)字,高32(左)位是epoch卿堂,低32位(右)用于遞增計數(shù)束莫。
- epoch:
ZAB協(xié)議通過epoch編號來區(qū)分Leader周期變化的策略,用來標識leader關(guān)系是否改變草描,每次一個leader被選出來览绿,它都會有一個新的epoch=(原來的epoch+1),標識當前屬于那個leader的統(tǒng)治時期穗慕《銮茫可以理解為當前集群所處的年代或者周期,每個leader就像皇帝逛绵,都有自己的年號怀各,所以每次改朝換代,leader變更之后术浪,都會在前一個年代的基礎(chǔ)上加1瓢对。這樣就算舊的leader崩潰恢復之后,也沒有人聽他的了胰苏,因為follower只聽從當前年代的leader的命令硕蛹。 - 計數(shù)器:
低 32 位是一個簡單的單調(diào)遞增的計數(shù)器,針對客戶端每個事務(wù)請求硕并,計數(shù)器加 1
leader服務(wù)器發(fā)生崩潰時分為如下場景:
- 1法焰、leader在提出proposal時未提交之前崩潰。
當leader接收到消息請求生成proposal后就掛了,其他follower并沒有收到此proposal,因此經(jīng)過恢復模式重新選了leader后沫屡,這條消息是被跳過的。 此時贵试,之前掛了的leader重新啟動并注冊成了follower琉兜,他保留了被跳過消息的proposal狀態(tài),與整個系統(tǒng)的狀態(tài)是不一致的毙玻,需要將其刪除豌蟋。leader都換代了,所以以前l(fā)eader的proposal失效了桑滩。 -
2梧疲、leader在發(fā)送commit消息之后,崩潰运准。
當leader收到合法數(shù)量follower的ack后幌氮,就向各個follower廣播commit命令,同時也會在本地執(zhí)行commit并向連接的客戶端返回「成功」胁澳。但是如果各個follower在收到commit命令前l(fā)eader就掛了该互,導致剩下的服務(wù)器并沒有執(zhí)行到這條消息。leader對事務(wù)消息發(fā)起commit操作韭畸,該消息在follower1上執(zhí)行了宇智,但是follower2還沒有收到commit,leader就已經(jīng)掛了胰丁,而實際上客戶端已經(jīng)收到該事務(wù)消息處理成功的回執(zhí)了随橘。所以在zab協(xié)議下需要保證所有機器都要執(zhí)行這個事務(wù)消息,必須滿足已經(jīng)被處理的消息不能丟失锦庸。
還沒有所有的follower提交這個事務(wù)机蔗,leader就掛了
Zab的解決機制:
1、新選舉出來的 Leader 不能包含未提交的 Proposal :
新選舉的 Leader 必須都是已經(jīng)提交了 Proposal 的 Follower 服務(wù)器節(jié)點甘萧。老的leader就算是及時恢復也不會被選為leader因為它有為提交的Proposal
2萝嘁、新選舉的 Leader 節(jié)點中含有最大的 zxid :
如果leader選舉算法能夠保證新選舉出來的Leader服務(wù)器擁有集群中所有機器最高編號(ZXID 最大)的事務(wù)Proposal,那么就可以保證這個新選舉出來的leader一定具有已經(jīng)提交的提案幔嗦。因為所有提案被commit之前必須有超過半數(shù)的follower ack酿愧,即必須有超過半數(shù)節(jié)點的服務(wù)器的事務(wù)日志上有該提案的proposal沥潭,因此只要有合法數(shù)量的節(jié)點正常工作邀泉,就肯定有一個節(jié)點保存了所有被commit消息的proposal狀態(tài)。
3钝鸽、新Leader 選出后:epoch +1汇恤、低32為清零、舊的proposal回滾
每當選舉產(chǎn)生一個新的 Leader 拔恰,就會從這個 Leader 服務(wù)器上取出本地事務(wù)日志充最大編號 Proposal 的 zxid因谎,并從 zxid 中解析得到對應的 epoch 編號,然后再對其加1颜懊,之后該編號就作為新的 epoch 值财岔,并將低32位數(shù)字歸零风皿,由0開始重新生成zxid。
當一個包含了上一個 Leader 周期中尚未提交過的事務(wù) Proposal 的服務(wù)器啟動時匠璧,當這臺機器加入集群中桐款,以 Follower 角色連上 Leader 服務(wù)器后,Leader 服務(wù)器會根據(jù)自己服務(wù)器上最后提交的 Proposal 來和 Follower 服務(wù)器的 Proposal 進行比對夷恍,比對的結(jié)果肯定是 Leader 要求 Follower 進行一個回退操作魔眨,回退到一個確實已經(jīng)被集群中過半機器 Commit 的最新 Proposal。
Zab 數(shù)據(jù)同步
1酿雪、完成 Leader 選舉后(新的 Leader 具有最高的zxid)遏暴,在正式開始工作之前(接收事務(wù)請求,然后提出新的 Proposal)指黎,Leader 服務(wù)器會首先確認事務(wù)日志中的所有的 Proposal 是否已經(jīng)被集群中過半的服務(wù)器 Commit朋凉。
2、Leader 服務(wù)器需要確保所有的 Follower 服務(wù)器能夠接收到每一條事務(wù)的 Proposal 醋安,并且能將所有已經(jīng)提交的事務(wù) Proposal 應用到內(nèi)存數(shù)據(jù)中侥啤。等到 Follower 將所有尚未同步的事務(wù) Proposal 都從 Leader 服務(wù)器上同步過啦并且應用到內(nèi)存數(shù)據(jù)中以后,Leader 才會把該 Follower 加入到真正可用的 Follower 列表中茬故。
leader選舉
服務(wù)器啟動時期的Leader選舉
假設(shè)我們擁有五臺zookeeper機器,分別為1,2,3,4,5,啟動順序依次排列,他們的myid分別為1,2,3,4,5,由于是服務(wù)器初始化啟動,原始數(shù)據(jù)皆為空,所以ZXID都為0盖灸,投票的格式為[myid,zxid];
此時,先啟動機器1,機器1首先投票給自己,選舉自己為Leader,記為[1,0],由于其它機器還沒有啟動所以它收不到反饋信息,服務(wù)器1的狀態(tài)一直屬于Looking(選舉狀態(tài));
啟動機器2,首先投票給自己,選舉自己為Leader,記為[2,0],此時接收到其他機器(機器1)的投票[1,0],與自己的投票進行對比,發(fā)現(xiàn)ZXID都一樣,都是0,則去對比myid大小,發(fā)現(xiàn)機器2的myid大,則機器2的投票不變,通知機器1更改投票結(jié)果,此時機器1,2投票都為[2,0],但此時投票數(shù)沒有大于半數(shù)磺芭,所以兩個服務(wù)器的狀態(tài)依然是LOOKING;
啟動機器3,首先投票給自己,選舉自己為Leader,記為[3,0],此時接收到其他機器(機器1,2)的投票[(2,0),(2,0)],與自己的投票進行對比,發(fā)現(xiàn)ZXID都一樣,都是0,則去對比myid大小,發(fā)現(xiàn)機器3的myid大,則機器3的投票不變,通知機器1,機器2更改投票結(jié)果,此時機器1,2投票更改為[3,0],此時超過了半數(shù)機器支持機器3作為Leader,此時選舉結(jié)束,機器3成為Leader,機器1,2作為Follower赁炎,此時機器3是LEADING狀態(tài),機器1,2是FOLLOWING狀態(tài);
啟動機器4,首先投票給自己,選舉自己為Leader,記為[4,0],此時接收到其他機器(機器1,2,3)的投票[(3,0),(3,0),(3,0)],與自己的投票進行對比,發(fā)現(xiàn)ZXID都一樣,都是0,則去對比myid大小,盡管發(fā)現(xiàn)機器4的myid大,但是因為第三部時已經(jīng)選舉出來機器3作為Leader,所以機器4只能作為Follower钾腺,所以機器4是FOLLOWING狀態(tài);
啟動機器5,結(jié)果同機器4徙垫;
其他的observer機器是OBSERVING狀態(tài),不參與投票
服務(wù)器運行時期的Leader選舉
在集群運行期間,有可能會發(fā)生新的節(jié)點加入或者Leader宕機的情況,如果是新節(jié)點加入,不會影響到Leader的更替(參見上面啟動機器4,5的情況),但如果是Leader機器宕機,則需要重新選舉Leader;
當發(fā)現(xiàn)Leader宕機,所有的非observer的機器狀態(tài)都會變成LOOKING,同時首先投票給自己選舉自己作為Leader,但此時有可能會出現(xiàn)不同機器的數(shù)據(jù)新舊不一致,大體步奏和服務(wù)器啟動時期的Leader選舉一致,唯一不同的是ZXID不同,需要選取ZXID最大的并且不包含未提交的Proposal的Follower作為Leader
zookeeper的讀寫流程
以3臺服務(wù)器的Zookeeper集群為例放棒,一個Leader姻报,兩個Follower即server1和server2
寫流程
(1)Client向Zookeeper的server1發(fā)送一個寫請求,客戶端寫數(shù)據(jù)到服務(wù)器1上间螟;
(2)如果server1不是Leader吴旋,那么server1會把接收到的寫請求轉(zhuǎn)發(fā)給Leader;然后Leader會將寫請求轉(zhuǎn)發(fā)給每個server厢破;server1和server2負責寫數(shù)據(jù)荣瑟,并且每個server的寫入數(shù)據(jù)是一致的,保存相同的數(shù)據(jù)副本摩泪;server1和server2寫數(shù)據(jù)成功后笆焰,通知Leader,此時server并沒有提交事務(wù)见坑;
(3)Leader收到集群半數(shù)以上的節(jié)點的寫操作成功的ACK嚷掠,這時捏检,客戶端就判定整個集群寫操作成功了,就通知各個server提交事務(wù)寫操作成功不皆。否則回滾事務(wù)未檩,寫操作失敗。
讀流程
相比寫數(shù)據(jù)流程粟焊,讀數(shù)據(jù)流程就簡單得多冤狡;因為每臺server中數(shù)據(jù)一致性都一樣,所以隨便訪問哪臺server讀數(shù)據(jù)就行项棠;沒有寫數(shù)據(jù)流程中請求轉(zhuǎn)發(fā)悲雳、數(shù)據(jù)同步、成功通知這些步驟香追。
zookeeper的數(shù)據(jù)模型
1合瓢、zookeeper的數(shù)據(jù)模型是一個樹形結(jié)構(gòu),Zookeeper將數(shù)據(jù)存儲于內(nèi)存中,Znode是存儲數(shù)據(jù)的最小單元透典。而Znode以層次化的結(jié)構(gòu)進行組織,形成一棵樹晴楔。其對外提供的視圖類似于Unix文件系統(tǒng)。樹的根Znode節(jié)點相當于Unix文件系統(tǒng)的根路徑峭咒。正如Unix中目錄下可以有子目錄一樣,znode結(jié)點下也可以掛載子結(jié)點,最終形成如下所示結(jié)構(gòu)税弃。
2、每一個znode節(jié)點都有各自的版本號, 可以通過命令行來顯示節(jié)點信息凑队,每當節(jié)點數(shù)據(jù)發(fā)生變化, 那么該節(jié)點的版本號會累加(樂觀鎖)则果,刪除/修改過時節(jié)點, 版本號不匹配會報錯,每個znode存儲的數(shù)據(jù)不宜過大, 幾k即可節(jié)點可以設(shè)置權(quán)限acl, 可以通過權(quán)限來限制用戶的訪問
znode的類型
持久節(jié)點:最常見的Znode類型,一旦創(chuàng)建將在一直存在于服務(wù)端,除非客戶端通過刪除操作進行刪除漩氨。持久結(jié)點下可以創(chuàng)建子結(jié)點西壮。
-
持久有序節(jié)點:在具有持久結(jié)點基本特性的基礎(chǔ)上,會通過在結(jié)點路徑后綴一串序號來區(qū)分多個子結(jié)點創(chuàng)建的先后順序。這工作由Zookeeper服務(wù)端自動給我們做,只要在創(chuàng)建Znode時指定結(jié)點類型為該類型叫惊。image.png
臨時節(jié)點:臨時結(jié)點的生命周期和客戶端會話保持一致款青。客戶端段會話存在的話臨時結(jié)點也存在,客戶端會話斷開則臨時結(jié)點會自動被服務(wù)端刪除霍狰。臨時結(jié)點下不能創(chuàng)建子結(jié)點抡草。
臨時有序節(jié)點:具有臨時結(jié)點的基本特性,又有順序性。
session會話的基本原理
sessions是服務(wù)端與客戶端連接的會話蚓耽,存在著固定的超時時間渠牲,超時則session被清除旋炒,客戶端可以向服務(wù)端發(fā)送ping包去保持有效的session步悠,也就是心跳機制,另外客戶端的心跳結(jié)束也會造成session被清除瘫镇,session過期的同時會刪除相應的臨時節(jié)點鼎兽。
wathcer機制
zk可以通過wathcer來實現(xiàn)事件的監(jiān)聽機制答姥,客戶端可以向服務(wù)端注冊一個wathcer來監(jiān)聽某一事件,客戶端操作zk的節(jié)點完成之后就會觸發(fā)wathcer事件谚咬,當監(jiān)控的znode對象發(fā)生了變化就會去觸發(fā)wathcer鹦付,wathcer類似數(shù)據(jù)庫的觸發(fā)器,但是這個觸發(fā)器是一次性的择卦,在進行觸發(fā)后就會被銷毀敲长,但是也可以通過一些Zookeeper的開源客戶端設(shè)置其為永久就不會被銷毀,Watcher是Zookeeper原生API中提供的事件監(jiān)聽接口,用戶要實現(xiàn)事件監(jiān)聽必須實現(xiàn)該接口并重寫process(WatchedEvent event)方法,該方法定義了客戶端在接收到服務(wù)端事件通知后的回調(diào)邏輯秉继。究竟服務(wù)端的什么事件可以被監(jiān)聽?按通知狀態(tài)劃分有SyncConnected,Disconnected,Expired,AuthFailed等好多種,這里主要講下SyncConnected狀態(tài)下的幾種事件類型:
Node(-1)
客戶端與服務(wù)端成功建立會話NodeCreated(1)
Watcher監(jiān)聽的對應Znode被創(chuàng)建NodeDeleted(2)
Watcher監(jiān)聽的Znode被刪除NodeDataChanged(3)
Watcher監(jiān)聽的Znode的數(shù)據(jù)內(nèi)容被改變,注意即使變更前后的數(shù)據(jù)內(nèi)容完全一樣也會觸發(fā)該事件,或者理解成該事件的觸發(fā)條件是Znode的版本號變更也沒問題NodeChildrenChanged(4)
Watcher監(jiān)聽的對應Znode的子結(jié)點發(fā)生變更
zookeeper的權(quán)限控制
直接看博客吧祈噪,不想寫了
http://www.reibang.com/p/4aa232ebf1cf
zookeeper的常用命令
先啟動zk,配置好zk的環(huán)境變量,啟動zk服務(wù)尚辑,和進入zk客戶端
help看看zk有什么命令
-
ls ls2 stat get 查看zk的目錄
ls /
ls2 / 辑鲤、stat / 、 get / 查看目錄及狀態(tài)消息
其狀態(tài)的含義:
- cZxid :創(chuàng)建節(jié)點的id
- ctime : 節(jié)點的創(chuàng)建時間
- mZxid :修改節(jié)點的id
- mtime :修改節(jié)點的時間
- pZxid :子節(jié)點的id
- cversion : 子節(jié)點的版本
- dataVersion : 當前節(jié)點數(shù)據(jù)的版本
- aclVersion :權(quán)限的版本
- ephemeralOwner :判斷是否是臨時節(jié)點
- dataLength : 數(shù)據(jù)的長度
- numChildren :子節(jié)點的數(shù)量
增刪改命令
create:創(chuàng)建杠茬、set:設(shè)置月褥、delete:刪除
create /xxxx xxxx 創(chuàng)建一個默認的臨時節(jié)點并賦值,此時節(jié)點的cversion 還是0
create -e /xxxx xxxx 創(chuàng)建一個臨時節(jié)點并賦值瓢喉,這個臨時節(jié)點在session會話過期或者是固定時間內(nèi)客戶端沒有發(fā)送心跳包就會自動清除宁赤,創(chuàng)建臨時節(jié)點后根節(jié)點的cversion加一了
create -a /xxxxx xxxxx 創(chuàng)建一個順序節(jié)點
set /xxxx xxxx 修改設(shè)置一個節(jié)點的值 在沒有set值之前dataVersion還是為0的,使用了set命令之后 dataVersion進行了加一操作
set /xxxx xxxx x 帶版本號的set操作栓票,版本號必須與節(jié)點的版本一致礁击,版本號不一致則報錯
delete /xxxx 刪除某節(jié)點 delete /xxxx x帶著版本號進行刪除,版本號不一致則報錯
watcher事件命令
通過 get /xxxx watch 逗载、ls /xxxx watch 哆窿、stat /xxxx wacth設(shè)置事件
ls /xxxx watch 為節(jié)點設(shè)置事件,創(chuàng)建子節(jié)點時觸發(fā)了NodeChildrenChanged事件厉斟,但是挚躯,在做set命令時沒有觸發(fā),原因在于watch觸發(fā)一次就會被銷毀
我們用 get /xxxx watch再次設(shè)置watch事件擦秽,在做set命令時觸發(fā)了NodeDataChanged事件
要注意的是如果修改子節(jié)點時码荔,是不會觸發(fā)NodeChildrenChanged,要觸發(fā)NodeChildrenChanged必須使用 get 命令對子節(jié)點設(shè)置watch
我們看到此時并沒有產(chǎn)生NodeChildrenChanged事件
當我們用get命令對子節(jié)點設(shè)置了事件后感挥,就觸發(fā)了NodeChildrenChanged事件
zk集群
在集群中哪個節(jié)點先啟動哪個節(jié)點就是master節(jié)點
集群最少是三臺機子缩搅,一般集群數(shù)量都是為奇數(shù)臺,也就是3触幼、5硼瓣、7、9.....
接下來我們要搭建一個偽分布式集群
先拷貝三個zk安裝目錄
配置安裝目錄下的zoo.cfg 在配置文件中最底下的三個ip和端口是,例如:server.1=192.168.200.128:2888:3888 server.1:代表第一臺機子堂鲤,第一臺機子是默認是集群的master 192.168.200.128:j機子的ip 2888:節(jié)點同步數(shù)據(jù)的端口號 3888:選舉的端口號
配置好zoo.cfg后亿傅,需要在zoo.cfg里配置的dataDir配置的位置增加一個myid文件配置,myid中配置相應的serverid,然后其他節(jié)點以此類推
最后啟動各個zk瘟栖,查看狀態(tài)
測試葵擎,在主節(jié)點創(chuàng)建一個節(jié)點,數(shù)據(jù)同步到了其他節(jié)點半哟,其他的節(jié)點修改了相應的數(shù)據(jù)時酬滤,各個節(jié)點也會跟著改變,各個節(jié)點的數(shù)據(jù)是保存一致的寓涨,偽分布式搭建成功
真分布式集群搭建
買了臺新電腦敏晤,配置夠開好幾個虛擬機了,哈哈哈
三臺機子的ip
配置第一臺機子缅茉,myid依然是1,
第二臺機子的zoo.cfg配置是一樣的嘴脾,只有改 dataLogDir和dataDir的位置就好了,myid設(shè)置為2蔬墩,所以第三臺機子也以此類推
配置好后译打,我把02先啟動,02成為了主節(jié)點拇颅,其他的01 03都是從節(jié)點
測試時奏司,任意節(jié)點修改后每個節(jié)點的數(shù)據(jù)依舊是保持一致的,所以真分布式集群搭建成功
zookeeper的選舉
完成真分布式搭建后樟插,我們把02主節(jié)點關(guān)機韵洋,讓01 03進行選舉
關(guān)閉02的電源
我們可以看到,01依舊是從節(jié)點黄锤,但是03已經(jīng)成為了主節(jié)點了
然后我們在重新把02開啟搪缨,并且啟動zk,此時我們發(fā)現(xiàn)02變成了從節(jié)點