zookeeper基礎知識

Zookeeper是什麼?
Zookeeper是一個高性能,分佈式的,開源分佈式應用協調服務。它提供了簡單原始的功能,分佈式應用可以基於它實現更高級的服務。它被設計爲易於編程,使用文件系統目錄樹作爲數據模型。服務端跑在java上,提供java和C的客戶端 API
基本概念
集羣角色:沒有Master/Slave概念,有Leader、Follower、Observer三個角色。Leader服務器爲客戶端提供
讀和寫服務。Follower和Observer都能提供讀服務,但Observer不參與Leader選舉過程。
會話:指客戶端和服務器之間的一個TCP連接。
節點:機器節點(集羣中的機器),數據節點(Znode數據模型中的數據單元,分爲持久節點和臨時節點)
版本:version、cversion等
Watcher:可在指定的節點上註冊事件,當事件觸發的時候,服務器會通知客戶端。
ACL:用來進行權限控制。
zookeeper可以用來做什麼
集羣服務,統一命名服務,分佈式配置管理,分佈式消息隊列,分佈式鎖,分佈式通知協調
等。
配置管理
在我們的應用中除了代碼外,還有一些就是各種配置。比如數據庫連接等。一般我們都是使用配置文件的方式,在代碼中引入這些配置文件。但是當我們只有一種配置,只有一臺服務器,並且不經常修改的時候,使用配置文件是一個很好的做法,但是如果我們配置非常多,有很多服務器都需要這個配置,而且還可能是動態的話使用配置文件就不是個好主意了。這個時候往往需要尋找一種集中管理配置的方法,我們在這個集中的地方修改了配置,所有對這個配置感興趣的都可以獲得變更。比如我們可以把配置放在數據庫裏,然後所有需要配置的服務都去這個數據庫讀取配置。但是,因爲很多服務的正常運行都非常依賴這個配置,所以需要這個集中提供配置服務的服務具備很高的可靠性。一般我們可以用一個集羣來提供這個配置服務,但是用集羣提升可靠性,那如何保證配置在集羣中的一致性呢? 這個時候就需要使用一種實現了一致性協議的服務了。Zookeeper就是這種服務,它使用Zab這種一致性協議來提供一致性。現在有很多開源項目使用Zookeeper來維護配置,比如在Hbase中,客戶端就是連接一個Zookeeper,獲得必要的hbase集羣的配置信息,然後纔可以進一步操作。還有在開源的消息隊列Kafka中,也使用Zookeeper來維護broker的信息。在Alibaba開源的SOA框架Dubbo中也廣泛的使用Zookeeper管理一些配置來實現服務治理。


名字服務
名字服務這個就很好理解了。比如爲了通過網絡訪問一個系統,我們得知道對方的IP地址,但是IP地址對人非常不友好,這個時候我們就需要使用域名來訪問。但是計算機是不能是別域名的。怎麼辦呢?如果我們每臺機器裏都備有一份域名到IP地址的映射,這個倒是能解決一部分問題,但是如果域名對應的IP發生變化了又該怎麼辦呢?於是我們有了DNS這個東西。我們只需要訪問一個大家熟知的(known)的點,它就會告訴你這個域名對應的IP是什麼。在我們的應用中也會存在很多這類問題,特別是在我們的服務特別多的時候,如果我們在本地保存服務的地址的時候將非常不方便,但是如果我們只需要訪問一個大家都熟知的訪問點,這裏提供統一的入口,那麼維護起來將方便得多了。


分佈式鎖
其實在第一篇文章中已經介紹了Zookeeper是一個分佈式協調服務。這樣我們就可以利用Zookeeper來協調多個分佈式進程之間的活動。比如在一個分佈式環境中,爲了提高可靠性,我們的集羣的每臺服務器上都部署着同樣的服務。但是,一件事情如果集羣中的每個服務器都進行的話,那相互之間就要協調,編程起來將非常複雜。而如果我們只讓一個服務進行操作,那又存在單點。通常還有一種做法就是使用分佈式鎖,在某個時刻只讓一個服務去幹活,當這臺服務出問題的時候鎖釋放,立即fail over到另外的服務。這在很多分佈式系統中都是這麼做,這種設計有一個更好聽的名字叫Leader Election(leader選舉)。比如HBase的Master就是採用這種機制。但要注意的是分佈式鎖跟同一個進程的鎖還是有區別的,所以使用的時候要比同一個進程裏的鎖更謹慎的使用。


集羣管理
在分佈式的集羣中,經常會由於各種原因,比如硬件故障,軟件故障,網絡問題,有些節點會進進出出。有新的節點加入進來,也有老的節點退出集羣。這個時候,集羣中其他機器需要感知到這種變化,然後根據這種變化做出對應的決策。比如我們是一個分佈式存儲系統,有一箇中央控制節點負責存儲的分配,當有新的存儲進來的時候我們要根據現在集羣目前的狀態來分配存儲節點。這個時候我們就需要動態感知到集羣目前的狀態。還有,比如一個分佈式的SOA架構中,服務是一個集羣提供的,當消費者訪問某個服務時,就需要採用某種機制發現現在有哪些節點可以提供該服務(這也稱之爲服務發現,比如Alibaba開源的SOA框架Dubbo就採用了Zookeeper作爲服務發現的底層機制)。還有開源的Kafka隊列就採用了Zookeeper作爲Cosnumer的上下線管理。


Zookeeper總體結構

Leader/Follower
ZooKeeper需要在所有的服務(可以理解爲服務器)中選舉出一個Leader,然後讓這個Leader來負責管理集羣。此時,集羣中的其它服務器則成爲此Leader的Follower。並且,當Leader故障的時候,需要ZooKeeper能夠快速地在Follower中選舉出下一個Leader。
Observer
Observer是zk集羣的另一個角色, observer的行爲在大多數情況下與follower完全一致, 但是他們不參加選舉和投票, 而僅僅接受(observing)選舉和投票的結果.
Zookeeper邏輯圖如下:


如上圖所示,假設搭建了一個5臺server的集羣,5臺機器根據選舉算法,選出一個leader,其他節點就是follower。
選舉好leader後會和每個server建立長連接
修改操作:當某個節點收到修改操作時,就會將請求轉發給leader,leader有處理機制,修改後同步到每一個follower。
zookeeper集羣搭建完成就可以啓動客戶端,客戶端可以連接除leader外的所有節點,建立長連接,客戶端任何修改信息都會同步到server上,由leader同步到各個節點
選舉:當leader掛掉後就會選舉一個新的leader,然後再重新建立連接。完成一次選舉大概需要200ms。
zookeeper中的概念
ZNode

zookeeper目錄樹中每一個節點對應一個Znode。每個Znode維護着一個屬性結構,它包含着版本號(dataVersion),時間戳(ctime,mtime)等狀態信息。ZooKeeper正是使用節點的這些特性來實現它的某些特定功能。每當Znode的數據改變時,他相應的版本號將會增加。每當客戶端檢索數據時,它將同時檢索數據的版本號。並且如果一個客戶端執行了某個節點的更新或刪除操作,他也必須提供要被操作的數據版本號。如果所提供的數據版本號與實際不匹配,那麼這個操作將會失敗。
Session
Client與ZooKeeper之間的通信,需要創建一個Session,這個Session會有一個超時時間。因爲ZooKeeper集羣會把Client的Session信息持久化,所以在Session沒超時之前,Client與ZooKeeper Server的連接可以在各個ZooKeeper Server之間透明地移動。
在實際的應用中,如果Client與Server之間的通信足夠頻繁,Session的維護就不需要其它額外的消息了。否則,ZooKeeper Client會每t/3 ms發一次心跳給Server,如果Client 2t/3 ms沒收到來自Server的心跳回應,就會換到一個新的ZooKeeper Server上。這裏t是用戶配置的Session的超時時間。
Watcher
ZooKeeper支持一種Watch操作,Client可以在某個ZNode上設置一個Watcher,來Watch該ZNode上的變化。如果該ZNode上有相應的變化,就會觸發這個Watcher,把相應的事件通知給設置Watcher的Client。
Zookeeper數據模型
zookeeper文件系統

zookeeper維護一個類似文件系統的數據結構
Zookeeper表現爲一個分層的文件系統目錄樹結構(不同於文件系統的是,節點可以有自己的數據,而文件系統中的目錄節點只有子節點)。
由根目錄和各個子目錄組成,每一個子目錄稱爲znode,znode類似文件夾,但是znode可以存儲數據
1) 持久化節點
所謂持久節點,是指在節點創建後,就一直存在,直到有刪除操作來主動清除這個節點——不會因爲創建該節點的客戶端會話失效而消失。
2) 持久化順序節點
這類節點的基本特性和上面的節點類型是一致的。額外的特性是,在ZK中,每個父節點會爲他的第一級子節點維護一份時序,會記錄每個子節點創建的先後順序。基於這個特性,在創建子節點的時候,可以設置這個屬性,那麼在創建節點過程中,ZK會自動爲給定節點名加上一個數字後綴,作爲新的節點名。這個數字後綴的範圍是整型的最大值。
3) 臨時節點
這類節點的基本特性和上面的節點類型是一致的。額外的特性是,在ZK中,每個父節點會爲他的第一級子節點維護一份時序,會記錄每個子節點創建的先後順序。基於這個特性,在創建子節點的時候,可以設置這個屬性,那麼在創建節點過程中,ZK會自動爲給定節點名加上一個數字後綴,作爲新的節點名。這個數字後綴的範圍是整型的最大值。
4) 臨時順序節點
可以用來實現分佈式鎖
客戶端調用create()方法創建名爲“_locknode_/guid-lock-”的節點,需要注意的是,這裏節點的創建類型需要設置爲EPHEMERAL_SEQUENTIAL。
客戶端調用getChildren(“_locknode_”)方法來獲取所有已經創建的子節點,注意,這裏不註冊任何Watcher。
客戶端獲取到所有子節點path之後,如果發現自己在步驟1中創建的節點序號最小,那麼就認爲這個客戶端獲得了鎖。
如果在步驟3中發現自己並非所有子節點中最小的,說明自己還沒有獲取到鎖。此時客戶端需要找到比自己小的那個節點,然後對其調用exist()方法,同時註冊事件監聽。
之後當這個被關注的節點被移除了,客戶端會收到相應的通知。這個時候客戶端需要再次調用getChildren(“_locknode_”)方法來獲取所有已經創建的子節點,確保自己確實是最小的節點了,然後進入步驟3。
節點特性:
節點類型(節點的生命週期):持久節點、臨時節點、順序節點。
狀態信息:包含事務ID、創建時間、版本號等信息。
版本:記錄節點的修改次數,用來保證分佈式數據的原子性操作(悲觀鎖:一個事務對數據進行處理時,在整個過程
都將數據鎖定,其它事務無法對這個數據進行更新,直到這個事務完成;樂觀鎖:假定多個事務在處理過程中不會彼此影響,所以
在大部分時間不需要加鎖)
通知機制
ZooKeeper支持一種Watch操作,Client可以在某個ZNode上設置一個Watcher,來Watch該ZNode上的變化。如果該ZNode上有相應的變化,就會觸發這個Watcher,把相應的事件通知給設置Watcher的Client。需要注意的是,ZooKeeper中的Watcher是一次性的,即觸發一次就會被取消,如果想繼續Watch的話,需要客戶端重新設置Watcher。這個跟epoll裏的oneshot模式有點類似。
Watcher:客戶端向服務端註冊一個Watcher,當服務端指定事件觸發時,就會向指定的客戶端發送一個事件通知。
Watcher接口、WatchedEvent、回調方法等等。
ZAB協議
ZAB協議(ZooKeeper Atomic Broadcast):是爲分佈式協調服務Zookeeper專門設計的一種支持崩潰恢復的原子廣播協議。
ZAB協議包括兩種基本模式:崩潰恢復和消息廣播。
在消息廣播中,Leader服務器會爲每一個Follower服務器各自分配一個單獨的隊列,將需要廣播的事務依次放入
這些隊列中,並根據FIFO(先進行出)的策略進行消息發送。
崩潰恢復:當Leader服務器出現崩潰或者由於網絡原因導致Leader服務器失去與過半Follower的聯繫,就進入崩潰恢復模式。
進程正常工作時,處於UP狀態;進程崩潰時,稱爲處於DOWN狀態。
ZAB協議是整個Zookeeper框架的核心所在,它規定任何時候都需要保證只有一個主進程負責進行消息廣播,如果主進程崩潰了
就要選舉一個新的主進程,選舉機制和消息廣播機制是緊密相關。
ZAB與Paxos的聯繫與區別:
聯繫:都存在類似於Leader進程的角色,負責協調多個Follower進程的運行;Leader進程都會等待超過半數的Follower做出正確
的反饋後,纔會將一個提案進行提交。
區別:設計目標不一樣。ZAB用於構建一個高可用的分佈式數據主備系統,Paxos用於構建分佈式一致性狀態機系統。
zk通信
通信協議:Zookeeper基於TCP/IP協議,實現了自己的通信協議來完成客戶端與服務器、服務器與服務器之間的網絡通信。
對於請求主要包括請求頭和請求體,對於響應,主要包含響應頭和響應體。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章