分佈式系統和應用,不只能提供更強的計算能力,還能爲咱們提供更好的容災性和擴展性。
算法
ZooKeeper是Google的Chubby項目的開源實現,它曾經做爲Hadoop的子項目,在大數據領域獲得普遍應用數據庫
ZooKeeper以Fast Paxos算法爲基礎,同時爲了解決活鎖問題,對Fast Paxos算法進行了優化,所以也能夠普遍用於大數據以外的其餘分佈式系統,爲大型分佈式系統提供可靠的協做處理功能。緩存
Apache ZooKeeper旨在減輕構建健壯的分佈式系統的任務。ZooKeeper基於分佈式計算的核心概念而設計,主要目的是給開發人員提供一套容易理解和開發的接口,從而簡化分佈式系統構建的任務。服務器
ZooKeeper的設計保證了其健壯性,這就使得應用開發人員能夠更多關注應用自己的邏輯,而不是協同工做上。ZooKeeper從文件系統API網絡
ZooKeeper從文件系統API獲得啓發,提供一組簡單的API,使得開發人員能夠實現通用的協做任務,包括選舉主節點、管理組內成員關係、管理元數據等。多線程
ZooKeeper包括一個應用開發庫(主要提供Java和C兩種語言的API)和一個用Java實現的服務組件。ZooKeeper的服務組件運行在一組專用服務器之上,實現的服務組件。架構
當你決定使用ZooKeeper來設計應用時,最好將應用數據和協同數據獨立開。整個ZooKeeper服務所管理的就是後者(協同數據,或稱元數據)併發
它能夠在分佈式系統中協做多個任務。框架
一個協做任務是指一個包含多個進程的任務。這個任務能夠是爲了協做或者是爲了管理競爭。異步
協做意味着多個進程須要一同處理某些事情,一些進程採起某些行動使得其餘進程能夠繼續工做
Apache HBase
HBase是一個一般與Hadoop一塊兒使用的數據存儲倉庫。在HBase中,ZooKeeper用於選舉一個集羣內的主節點,以便跟蹤可用的服務器,並保存集羣的元數據。
Apache Kafka
Kafka是一個基於發佈-訂閱(pub-sub)模型的消息系統。其中ZooKeeper用於檢測崩潰,實現主題(topic)的發現,並保持主題的生產和消費狀態。
Apache Solr
Solr是一個企業級的搜索平臺。Solr的分佈式版本命名爲SolrCloud,它使用ZooKeeper來存儲集羣的元數據,並協做更新這些元數據。
Yahoo!Fetching Service
Yahoo!Fetching Service是爬蟲實現的一部分,經過緩存內容的方式高效地獲取網頁信息,同時確保知足網頁服務器的管理規則(好比robots.txt文件)。該服務採用ZooKeeper實現主節點選舉、崩潰檢測和元數據存儲。
Facebook Messages
Facebook推出的這個應用(http://on.fb.me/1a7uViK )集成了email、短信、Facebook聊天和Facebook收件箱等通訊通道。該應用將ZooKeeper做爲控制器,用來實現數據分片、故障恢復和服務發現等功能。
Zookeep的客戶端API功能強大,其中包括:
ZooKeeper以前的其餘一些系統採用分佈式鎖管理器或者分佈式數據庫來實現協做。實際上,ZooKeeper也從這些系統中借鑑了不少概念。
可是,ZooKeeper的設計更專一於任務協做,並不提供任何鎖的接口或通用存儲數據接口。同時,ZooKeeper沒有給開發人員強加任何特殊的同步原語,使用起來很是靈活。
ZooKeeper可讓開發人員更專一於其應用自己的邏輯而不是神祕的分佈式系統概念
整個ZooKeeper的服務器集羣管理着應用協做的關鍵數據。ZooKeeper不適合用做海量數據存儲。最佳實踐仍是應該將應用數據和協同數據獨立開
ZooKeeper中實現了一組核心操做,經過這些能夠實現不少常見分佈式應用的任務。ZooKeeper並無爲你實現這些任務(應用服務採用主節點方式或進程響應跟蹤方式?),也沒有爲應用實現主節點選舉,或者進程存活與否的跟蹤的功能,可是,ZooKeeper提供了實現這些任務的工具,對於實現什麼樣的協同任務,由開發人員本身決定。
分佈式系統是同時跨越多個物理主機,獨立運行的多個軟件組件所組成的系統
採用分佈式去設計系統有不少緣由,
分佈式系統可以利用多處理器的運算能力來運行組件,好比並行復制任務。
一個系統也許因爲戰略緣由,須要分佈在不一樣地點,好比一個應用由多個不一樣地點的服務器提供服務。
使用一個獨立的協調組件有幾個重要的好處:
首先,咱們能夠獨立地設計和實現該組件,這樣獨立的組件能夠跨多個應用共享。
其次,系統架構師能夠簡化協做方面的工做,這些並非瑣碎的小事
最後,系統能夠獨立地運行和協做這些組件,獨立這樣的組件,也簡化了生產環境中解決實際問題的任務。
軟件組件以操做系統的進程方式運行,不少時候還涉及多線程的執行。所以ZooKeeper的服務端和客戶端也是以進程的方式運行,一個單獨的物理主機(不管是一個獨立主機仍是一個虛擬環境中的操做系統)上運行一個單獨的應用進程,儘管進程可能採用多線程運行的方式,以便利用現代處理器的多核(multicore)處理能力。
分佈式系統中的進程通訊有兩種選擇:直接經過網絡進行信息交換,或讀寫某些共享存儲。
ZooKeeper使用共享存儲模型來實現應用間的協做和同步原語。
對於共享存儲自己,又須要在進程和存儲間進行網絡通訊。咱們強調網絡通訊的重要性,由於它是分佈式系統中併發設計的基礎。
在真實的系統中,咱們須要特別注意如下問題:
關於這些問題的一個重要結果是,在實際狀況中,咱們很難判斷一個進程是崩潰了仍是某些因素致使了延時
ZooKeeper的精確設計簡化了這些問題的處理,ZooKeeper並非徹底消除這些問題,而是將這些問題在應用服務層面上徹底透明化,使得這些問題更容易處理。
ZooKeeper實現了重要的分佈式計算問題的解決方案,直觀爲開發人員提供某種程度上實現的封裝,至少這是咱們一直但願的。
通常在這種架構中,主節點進程負責跟蹤從節點狀態和任務的有效性,並分配任務到從節點。
要實現主-從模式的系統,咱們必須解決如下三個關鍵問題:
爲了處理這些問題,
以前的主節點出現問題時,系統須要可靠地選舉一個新的主節點,
判斷哪些從節點有效,並斷定一個從節點的狀態相對於系統其餘部分是否失效。
主節點失效時,咱們須要有一個備份主節點(backup master)。
備份主節點接管主要主節點的角色,進行故障轉移
狀態恢復:新的主要主節點須要可以恢復到舊的主要主節點崩潰時的狀態
對於主節點狀態的可恢復性,咱們不能依靠從已經崩潰的主節點來獲取這些信息,而須要從其餘地方獲取,也就是經過ZooKeeper來獲取。
錯誤的假設:假如主節點有效,備份主節點卻認爲主節點已經崩潰
例如主節點負載很高,致使消息任意延遲,備份主節點將會接管成爲主節點的角色,執行全部必需的程序,最終可能以主節點的角色開始執行,成爲第二個主要主節點。
更糟的是,若是一些從節點沒法與主要主節點通訊,如因爲網絡分區(network partition)錯誤致使,這些從節點可能會中止與主要主節點的通訊,而與第二個主要主節點創建主-從關係。針對這個場景中致使的問題,咱們通常稱之爲腦裂(split-brain):系統中兩個或者多個部分開始獨立工做,致使總體行爲不一致性。咱們須要找出一種方法來處理主節點失效的狀況,關鍵是咱們須要避免發生腦裂的狀況。
從節點失效
若是從節點崩潰了,全部已派發給這個從節點且還沒有完成的任務須要從新派發。
首要需求是讓主節點具備檢測從節點的崩潰的能力。
一個從節點崩潰時,從節點也許執行了部分任務,也許所有執行完,但沒有報告結果。若是整個運算過程產生了其餘做用,咱們還有必要執行某些恢復過程來清除以前的狀態。
若是一個從節點與主節點的網絡鏈接斷開,好比網絡分區(network partition)致使,從新分配一個任務可能會致使兩個從節點執行相同的任務。
若是一個任務容許屢次執行,咱們在進行任務再分配時能夠不用驗證第一個從節點是否完成了該任務。
若是一個任務不容許,那麼咱們的應用須要適應多個從節點執行相同任務的可能性。
通訊故障致使的另外一個重要問題是對鎖等同步原語的影響。
首先,客戶端能夠告訴ZooKeeper某些數據的狀態是臨時狀態(ephemeral);
其次,同時ZooKeeper須要客戶端定時發送是否存活的通知,若是一個客戶端未能及時發送通知,那麼全部從屬於這個客戶端的臨時狀態的數據將所有被刪除。
經過這兩個機制,在崩潰或通訊故障發生時,咱們就能夠預防客戶端獨立運行而發生的應用宕機。
理想的方式是,以上每個任務都須要經過原語的方式暴露給應用,對開發者徹底隱藏實現細節。
ZooKeeper提供了實現這些原語的關鍵機制,所以,開發者能夠經過這些實現一個最適合他們需求、更加關注應用邏輯的分佈式應用。
配置信息也許發生了變化,咱們能夠中止全部進程,從新分發配置信息的文件,而後從新啓動,可是從新配置就會延長應用的停機時間。
組成員關係的問題,當負載變化時,咱們但願增長或減小新機器和進程。
當你在開發分佈式應用時,你就會遇到真正困難的問題,你就不得不面對故障,如崩潰、通訊故障等各類狀況。這些問題會在任何可能的點忽然出現,甚至沒法列舉須要處理的全部的狀況。
拜占庭將軍問題(Byzantine Faults)
在獨立主機上運行的應用與分佈式應用發生的故障存在顯著的區別:
在分佈式應用中,可能會發生局部故障,
當獨立主機崩潰,這個主機上運行的全部進程都會失敗,
若是是獨立主機上運行多個進程,一個進程執行的失敗,其餘進程能夠經過操做系統得到這個故障,操做系統提供了健壯的多進程消息通訊的保障。
在分佈式環境中這一切發生了改變:若是一個主機或進程發生故障,其餘主機繼續運行,並會接管發生故障的進程,爲了可以處理故障進程,這些仍在運行的進程必須可以檢測到這個故障,不管是消息丟失或發生了時間偏移。
FLP(由其做者命名:Fischer,Lynch,Patterson),這個結論證實了在異步通訊的分佈式系統中,進程崩潰,全部進程可能沒法在這個比特位的配置上達成一致 [1] 。
相似的定律稱爲CAP,表示一致性(Consistency)、可用性(Availability)和分區容錯性(Partitiontolerance),該定律指出,當設計一個分佈式系統時,咱們但願這三種屬性所有知足,但沒有系統能夠同時知足這三種屬性 [2] 。
所以ZooKeeper的設計儘量知足一致性和可用性,固然,在發生網絡分區時ZooKeeper也提供了只讀能力。
所以,咱們沒法擁有一個理想的故障容錯的、分佈式的、真實環境存在的系統來處理可能發生的全部問題。但咱們仍是能夠爭取一個稍微不那麼宏偉的目標。
首先,咱們只好對咱們的假設或目標適當放鬆,例如,咱們能夠假設時鐘在某種範圍內是同步的,咱們也能夠犧牲一些網絡分區容錯的能力並認爲其一直是一致的,當一個進程運行中,也許屢次因沒法肯定系統中的狀態而被認爲已經發生故障。雖然這些是一些折中方案,而這些折中方案容許咱們創建一些印象很是深入的分佈式系統。
不得不指出,完美的解決方案是不存在的,咱們重申ZooKeeper沒法解決分佈式應用開發者面對的全部問題,而是爲開發者提供了一個優雅的框架來處理這些問題。
多年以來,ZooKeeper在分佈式計算領域進行了大量的工做。Paxos算法 [1] 和虛擬同步技術(virtual synchrony) [2]給ZooKeeper的設計帶來了很大影響,經過這些技術能夠無縫地處理所發生的某些變化或狀況,並提供給開發者一個框架,來應對沒法自動處理的某些狀況。
能夠很容易地部署ZooKeeper集羣,輕鬆經過這個集羣開發應用,但實際上,在使用ZooKeeper時,有些狀況ZooKeeper自身沒法進行決策而是須要開發者本身作出決策,有些開發者並不徹底瞭解這些。