姓名:劉保闊
學(xué)號:19021210887
轉(zhuǎn)自:https://blog.csdn.net/HarderXin/article/details/103975611
【嵌牛導(dǎo)讀】
????????Zookeeper主要是基于文件系統(tǒng)和監(jiān)聽通知機制,可以用于統(tǒng)一命名服務(wù)、分布式配置管理、集群管理、分布式鎖、分布式隊列、負(fù)載均衡等功能。
【嵌牛正文】
文件系統(tǒng)結(jié)構(gòu)
Zookeeper維護一個類似文件系統(tǒng)的數(shù)據(jù)結(jié)構(gòu):

每一個子目錄,如NameService稱之為一個znode目錄節(jié)點,和文件系統(tǒng)一樣,我們可以對znode節(jié)點進行添加、刪除操作,在znode的子節(jié)點下添加刪除操作,唯一的不同是znode是可以保存數(shù)據(jù)的,數(shù)據(jù)還包含當(dāng)前版本、數(shù)據(jù)版本、建立時間和修改時間等
數(shù)據(jù)類型
Zookeeper支持四種類型的節(jié)點數(shù)據(jù):
持久化目錄節(jié)點(persistent):客戶端與zookeeper斷開連接后,該節(jié)點依然存在
持久化順序編號目錄節(jié)點(persistent_sequential):與持久化目錄節(jié)點一樣,不過Zookeeper給該節(jié)點進行順序編號
臨時目錄節(jié)點(ephemeral):客戶端與zookeeper斷開連接后,該節(jié)點被刪除
臨時順序編號目錄節(jié)點(ephemeral_sequential):與臨時目錄節(jié)點一樣,不過Zookeeper給該節(jié)點進行順序編號
監(jiān)聽通知機制
客戶端監(jiān)聽它所關(guān)心的目錄節(jié)點,當(dāng)目錄節(jié)點發(fā)生變化(數(shù)據(jù)改變、刪除、子目錄節(jié)點發(fā)生變化)的時候,zookeeper會通知客戶端,在Zookeeper中,默認(rèn)有二種角色,F(xiàn)ollower、Leader,一個Zookeeper集群在同一時刻只會有一個Leader,其余都是Follower,我們還可以添加Observer角色,如果想使用Observer模式,在任何想變成Observer的節(jié)點的配置文件中加入:peerType=Observer。Leader服務(wù)器可以為客戶端提供讀和寫操作,而Follower和Observer都只能提供讀服務(wù),唯一的區(qū)別是Observer不參與Leader選舉過程,也不參與寫操作(過半寫成功)策略,因此Observer可以在不影響寫性能的情況下提升集群的讀性能。
應(yīng)用場景
Zookeeper所有的功能都是基于文件系統(tǒng)和監(jiān)聽通知機制來完成的,下面來講解一下各個功能的實現(xiàn)原理:
分布式配置管理

在大型系統(tǒng)中,我們部署的項目可能超過上百臺機器,當(dāng)我們在修改配置的時候,不可能每一臺機器都去修改一下,這樣維護起來太復(fù)雜了,所以我們可以將配置文件通過Zookeeper來管理,在Zookeeper中創(chuàng)建一個Configuration的目錄節(jié)點,所有應(yīng)用程序都監(jiān)聽這個目錄節(jié)點,一旦配置文件的信息發(fā)生變化,Zookeeper會通知每個應(yīng)用,然后每個應(yīng)用從Zookeeper中獲取最新的配置信息。
Zookeeper集群環(huán)境

如上圖,我們在三臺服務(wù)器上部署了Zookeeper的集群環(huán)境,在三臺機器的Zookeeper啟動完成后,會選舉一臺機器為Leader,負(fù)責(zé)客戶端的的讀和寫請求,其他兩條機器為Follower,只能負(fù)責(zé)讀請求
場景模擬:當(dāng)我們通過zkclient在192.168.1.1的機器上創(chuàng)建了一個/hello的數(shù)據(jù)節(jié)點,會發(fā)現(xiàn)這臺Follower也能寫成功,并且在192.168.1.2或者192.168.1.3的機器上都能夠獲取到,那么是不是就與上面的Follower只能負(fù)責(zé)讀理論沖突了?其實并沒有沖突,而是Follower在接受到寫請求后,它會將寫請求轉(zhuǎn)給Leader節(jié)點,讓Leader節(jié)點去處理寫請求,Leader寫成功后會通知同步到各個Follower節(jié)點,這樣做的目的是保證數(shù)據(jù)的唯一性,過程如下:

1、 Client向Follower發(fā)起一個寫請求
2、 Follower把寫請求轉(zhuǎn)發(fā)給Leader
3、 Leader接收到請求以后開始發(fā)起投票并通知Follower進行投票
4、 Follower把投票結(jié)果發(fā)送給Leader
5、 Leader將結(jié)果匯總,發(fā)現(xiàn)如果超過一半的節(jié)點支持寫入,那么投票成功,則開始寫入同時把寫入操作通知給Follower,然后commit
6、 Follower把請求結(jié)果返回給Client
集群選舉原理

還是拿上面的寫請求作為分析案例,當(dāng)我們的Follower向Leader發(fā)送一個寫請求后,會在Leader節(jié)點生成一個全局唯一的嚴(yán)格保證順序遞增的事務(wù)ID(ZXID),因為讀不會有事務(wù)的概念,寫才有事務(wù)的概念,生成后Leader節(jié)點會向所有的Follower節(jié)點服務(wù)器發(fā)送請求,并且所有的Follower服務(wù)器會發(fā)送一個收到事務(wù)通知的確認(rèn)消息到Leader服務(wù)器,只要Leader服務(wù)器收到超過一半的Follower服務(wù)器發(fā)過來的確認(rèn)消息,Leader服務(wù)器就可以開始做Commit操作,同時也通知其他Follower服務(wù)器做Commit操作,這樣在一臺Follower服務(wù)器上寫數(shù)據(jù)后,其他服務(wù)器都能夠同步更新,這里面涉及到兩階段提交,這樣做的目的是保證了數(shù)據(jù)的一致性,性能也比較高。
如果其中Leader節(jié)點因為某種原因而導(dǎo)致服務(wù)器掛了,那么如何保證高可用呢,Zookeeper會通過集群選舉一個新的節(jié)點作為Leader節(jié)點,實現(xiàn)如下:當(dāng)Leader節(jié)點不可用的時候,所有的Follower節(jié)點會向集群中其他的存活的Follower節(jié)點發(fā)送投票消息,該消息格式為(myid,zxid),每臺服務(wù)器當(dāng)然是優(yōu)先投自己,其中myid為集群搭建的時候我們自己配置的,zxid為該服務(wù)器最新的zxid,每臺機器的zxid由于受到Leader消息的前后可能會不一樣,當(dāng)每臺機器接受到來自不同F(xiàn)ollower發(fā)送的消息后,根據(jù)最大的zxid進行pk,誰的最大,誰的票數(shù)最多,然后其他的票數(shù)作廢,因為最大的zxid的服務(wù)器肯定能保證數(shù)據(jù)是最新最全的,當(dāng)每臺服務(wù)器選舉出來結(jié)果后會做更新操作,同時會向其他服務(wù)器發(fā)通知,其他服務(wù)器收到投票通知后,當(dāng)其中一臺服務(wù)器得到的票數(shù)大于總服務(wù)器數(shù)的一半,那么該服務(wù)器就成功選舉成為Leader,所以我們在搭建集群環(huán)境的時候,最好搭建的集群數(shù)量為奇數(shù),集群Leader選舉和集群消息廣播(兩階段提交)的組合就是zab原子廣播協(xié)議。Zookeeper沒有用到paxos算法來保證數(shù)據(jù)一致性,zab協(xié)議其實是paxos算法的一個變種。
分布式鎖
分布式鎖主要用于在分布式環(huán)境中保護跨進程、跨主機、跨網(wǎng)絡(luò)的共享資源實現(xiàn)互斥訪問,以達到保證數(shù)據(jù)的一致性。Zookeeper實現(xiàn)分布式鎖是通過持久節(jié)點和臨時順序節(jié)點來完成的,實現(xiàn)思路如下:

1、 在指定目錄下創(chuàng)建一個持久節(jié)點,例如lock節(jié)點(zookeeper里面的znode節(jié)點會自動同步,而且是強一致性的,創(chuàng)建一個節(jié)點后只有zookeeper集群同步完成后才算成功)
2、 每當(dāng)進程需要訪問共享資源的時候,會在lock下面建立響應(yīng)的順序臨時子節(jié)點,例如tmp_node1、tmp_node2、tmp_node3
3、 建立臨時順序子節(jié)點后,判斷建立的子節(jié)點的順序號(臨時子節(jié)點創(chuàng)建會自動生成一個順序號)是否為最小節(jié)點,如果是最小節(jié)點,就可以獲得鎖對資源進行訪問
4、 如果該節(jié)點不是最小節(jié)點,那么就獲得該節(jié)點的上一個順序節(jié)點,并給該節(jié)點注冊監(jiān)聽事件監(jiān)聽
5、 當(dāng)客戶端關(guān)閉與zookeeper連接之后,會刪除當(dāng)前的臨時子節(jié)點,釋放當(dāng)前的鎖,下面的臨時節(jié)點會得到通知,并判斷自己的節(jié)點是否為當(dāng)前最小的,如果是則獲取共享鎖,如果不是則繼續(xù)第4步對比自己小的節(jié)點注冊監(jiān)聽事件
流程如下:

原文鏈接:https://blog.csdn.net/HarderXin/article/details/103975611