ZooKeeper簡介(淺入)

1. 產生背景

當今是個分佈式、集羣、雲計算等名詞滿天飛的時代。形成這種局面的一個重要因素就是,單一機器的處理能力已經不能知足咱們的需求,不得不採用由多臺機器組成的服務集羣。
服務集羣對外提供服務的過程當中,能夠分解處理壓力,在必定程度上打破性能瓶頸,並提升服務的可用性(不會由於一臺機器宕機而形成服務不可用)。html

上圖中有三臺機器,每臺機器跑一樣的一個應用程序。而後咱們將這三臺機器經過網絡將其鏈接起來,構成一個系統來爲用戶提供服務,對用戶來講這個系統的架構是透明的,他感受不到這個系統是一個什麼樣的架構。那麼咱們就能夠把這種系統稱做一個分佈式系統。
那麼,問題來了:
(1)程序的運行每每依賴不少配置文件,好比數據庫地址、黑名單控制、服務地址列表等,並且有些配置信息須要頻繁地進行動態變動,這時候怎麼保證全部機器共享的配置信息保持一致?

(2)若是有一臺機器掛掉了,其餘機器如何感知到這一變化並接管任務?若是用戶激增,須要增長機器來緩解壓力,如何作到不重啓集羣而完成機器的添加?java

(3)用戶數量增長或者減小,會出現有的機器資源使用率繁忙,有的卻空閒,如何讓每臺機器感知到其餘機器的負載狀態從而實現負載均衡?linux

(4)在一臺機器上要多個進程或者多個線程操做同一資源比較簡單,由於能夠有大量的狀態信息或者日誌信息提供保證,好比兩個A和B進程同時寫一個文件,加鎖就能夠實現。可是分佈式系統怎麼辦?須要一個三方的分配鎖的機制,幾百臺worker都對同一個網絡中的文件寫操做,怎麼協同?還有怎麼保證高效的運行?數據庫

2. ZooKeeper的前世此生

分佈式系統的不少難題,都是因爲缺乏協調機制形成的。編程

目前,在分佈式協調技術方面作得比較好的就是Google的Chubby還有Apache的ZooKeeper。 有人會問既然有了Chubby爲何還要弄一個ZooKeeper,難道Chubby作得不夠好嗎?主要是Chubby是非開源的,Google自家用。後來雅虎模仿Chubby開發出了ZooKeeper,也實現了相似的分佈式鎖的功能,而且將ZooKeeper做爲一種開源的程序捐獻給了Apache,那麼這樣就可使用ZooKeeper所提供鎖服務。bash

至於這個神器爲何叫ZooKeeper,與外國人一向的幽默精神有關。衆所周知,外國人喜歡給用一個動物做爲吉祥物,在IT界也不例外。好比:服務器

負責大數據工做的Hadoop是一個黃色的大象 網絡

負責數據倉庫的Hive是一個虛擬蜂巢
負責數據分析的Apache Pig是一頭聰明的豬
負責管理Web容器的Tomcat是一隻雄貓……
那好,負責分佈式協調工做的角色就叫ZooKeeper(動物園飼養員)吧。

3. Zookeeper是什麼

隨着大數據的火熱,Hxx(根據MapReduce,因而咱們有了Hadoop;根據GFS,因而咱們有了HDFS;根據BigTable,因而咱們有了HBase)們已經變得耳熟能詳,如今做爲一個開發人員若是都不知道這幾個名詞出門都好像很差意思跟人打招呼。架構

但實際上對咱們這些非大數據開發人員而言,Zookeeper是比Hxx們可能接觸到更多的一個基礎服務。可是,無奈的是它一直默默的位於二線,歷來沒有Hxx們那麼耀眼。那麼到底什麼是Zookeeper呢?Zookeeper能夠用來幹什麼?咱們將如何使用Zookeeper?Zookeeper又是怎麼實現的?併發

伴隨着Zookeeper有兩篇論文:一篇是Zab,就是介紹Zookeeper背後使用的一致性協議的(Zookeeper atomic broadcast protocol),還有一篇就是介紹Zookeeper自己的。在這兩篇論文裏都提到Zookeeper是一個分佈式協調服務(a service for coordinating processes of distributed applications)。那分佈式協調服務又是個什麼東西呢?首先咱們來看「協調」是什麼意思。

說到協調,我首先想到的是北京不少十字路口的交通協管,他們手握小紅旗,指揮車輛和行人是否是能夠通行。若是咱們把車輛和行人比喻成運行在計算機中的單元(線程),那麼這個協管是幹什麼的?不少人都會想到,這不就是鎖麼?對,在一個併發的環境裏,咱們爲了不多個運行單元對共享數據同時進行修改,形成數據損壞的狀況出現,咱們就必須依賴像鎖這樣的協調機制,讓有的線程能夠先操做這些資源,而後其餘線程等待。對於進程內的鎖來說,咱們使用的各類語言平臺都已經給咱們準備不少種選擇。就拿Java來講,有最普通不過的同步方法或同步塊:

public synchronized void sharedMethod(){
   //對共享數據進行操做
}
複製代碼

使用了這種方式後,多個線程對sharedMethod進行操做的時候,就會協調好步驟,不會對sharedMethod裏的資源進行破壞,產生不一致的狀況。
這是最簡單的協調方法,但有的時候咱們可能須要更復雜的協調。好比咱們經常爲了提升性能,咱們使用讀寫鎖。由於大部分時候咱們對資源是讀多寫少,而若是無論三七二十一所有使用排他的寫鎖,那麼性能有可能就會受到影響。仍是用java舉例:

public class SharedSource{
   private ReadWriteLock rwlock = new ReentrantReadWriteLock();
   private Lock rlock = rwlock.readLock();
   private Lock wlock = rwlock.writeLock();

   public void read(){
      rlock.lock();
      try{
         //讀取資源
      }finally{
         rlock.unlock();
      }
   }
   
   public void write(){
     wlock.lock();
     try{
        //寫資源
     }finally{
        wlock.unlock();
     }
   }

}
複製代碼

咱們在進程內還有各類各樣的協調機制(通常咱們稱之爲同步機制)。如今咱們大概瞭解了什麼是協調了,可是上面介紹的協調都是在進程內進行協調。在進程內進行協調咱們可使用語言,平臺,操做系統等爲咱們提供的機制。那麼若是咱們在一個分佈式環境中呢?也就是咱們的程序運行在不一樣的機器上,這些機器可能位於同一個機架,同一個機房又或不一樣的數據中心。在這樣的環境中,咱們要實現協調該怎麼辦?那麼這就是分佈式協調服務要乾的事情。

ok,可能有人會講,這個好像也不難。無非是將原來在同一個進程內的一些原語經過網絡實如今分佈式環境中。是的,表面上是能夠這麼說。但分佈式系統中,說每每比作容易得多。在分佈式系統中,全部同一個進程內的任何假設都不存在:由於網絡是不可靠的。

好比,在同一個進程內,你對一個方法的調用若是成功,那就是成功(固然,若是你的代碼有bug那就另說了),若是調用失敗,好比拋出異常那就是調用失敗。在同一個進程內,若是這個方法先調用先執行,那就是先執行。可是在分佈式環境中呢?

因爲網絡的不可靠,你對一個服務的調用失敗了並不表示必定是失敗的,多是執行成功了,可是響應返回的時候失敗了。還有,A和B都去調用C服務,在時間上A還先調用一些,B後調用,那麼最後的結果是否是必定A的請求就先於B到達呢? 這些原本在同一個進程內的種種假設咱們都要從新思考,咱們還要思考這些問題給咱們的設計和編碼帶來了哪些影響。還有,在分佈式環境中爲了提高可靠性,咱們每每會部署多套服務,可是如何在多套服務中達到一致性,這在同一個進程內很容易解決的問題,但在分佈式環境中確實一個大難題。

因此分佈式協調遠遠比同一個進程裏的協調複雜得多,因此相似Zookeeper這類基礎服務就應運而生。這些系統都在各個系統久經考驗,它的可靠性,可用性都是通過理論和實踐的驗證的。因此咱們在構建一些分佈式系統的時候,就能夠以這類系統爲起點來構建咱們的系統,這將節省很多成本,並且bug也將更少。

上述試圖從外圍介紹一下Zookeeper是一個什麼樣子的服務和咱們爲何須要這樣一種服務。接下來會介紹Zookeeper到底能幹些什麼。

4. Zookeeper能夠幹什麼

在Zookeeper的官網上有這麼一句話:ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services.

這大概描述了Zookeeper主要能夠幹哪些事情:配置管理名字服務分佈式同步以及集羣管理。那這些服務又究竟是什麼呢?咱們爲何須要這樣的服務?咱們又爲何要使用Zookeeper來實現呢,使用Zookeeper有什麼優點?接下來我會挨個介紹這些究竟是什麼,以及有哪些開源系統中使用了。

  • 配置管理
    在咱們的應用中除了代碼外,還有一些就是各類配置。好比數據庫鏈接等。通常咱們都是使用配置文件的方式,在代碼中引入這些配置文件。當咱們只有一種配置、一臺服務器,而且不常常修改的時候,使用配置文件是一個很好的作法,可是若是咱們配置很是多,有不少服務器都須要這個配置,並且還多是動態的話使用配置文件就不是個好主意了。這個時候每每須要尋找一種集中管理配置的方法,咱們在這個集中的地方修改了配置,全部對這個配置感興趣的均可以得到變動。

    好比把這公用的配置文件提取出來放到一個地方,對這個地方(目錄節點)進行監聽,一旦配置信息發生變化,每一個應用程序就會收到Zookeeper的通知,而後從Zookeeper獲取新的配置信息應用到系統中。可是,由於不少服務的正常運行都很是依賴這個配置,因此須要這個集中提供配置服務的服務具有很高的可靠性。通常咱們能夠用一個集羣來提供這個配置服務,可是用集羣提高可靠性,那如何保證配置在集羣中的一致性呢?

    這個時候就須要使用一種實現了一致性協議的服務了。Zookeeper就是這種服務,它使用Zab這種一致性協議來提供一致性。如今有不少開源項目使用Zookeeper來維護配置,好比,在開源的消息隊列Kafka中,也使用Zookeeper來維護broker的信息;在Alibaba開源的SOA框架Dubbo中也普遍的使用Zookeeper管理一些配置來實現服務治理;在HBase中,客戶端就是鏈接一個Zookeeper,得到必要的HBase集羣的配置信息,而後才能夠進一步操做。

  • 命名服務
    命名服務這個就很好理解了。好比爲了經過網絡訪問一個系統,咱們得知道對方的IP地址,可是IP地址對人很是不友好,這個時候咱們就須要使用域名來訪問。可是計算機是不能識別域名的。怎麼辦呢?若是咱們每臺機器裏都有一份域名到IP地址的映射,這個卻是能解決一部分問題,可是若是域名對應的IP發生變化了又該怎麼辦呢?

    因而咱們有了DNS這個東西。咱們只須要訪問一個你們熟知的(known)的點,它就會告訴你這個域名對應的IP是什麼。在咱們的應用中也會存在不少這類問題,特別是在咱們的服務特別多的時候,若是咱們在本地保存服務的地址將很是不方便,可是若是咱們只須要訪問一個你們都熟知的訪問點,這裏提供統一的入口,那麼維護起來將方便多了。

    好比,用過Duboo+Zookeeper整合的系統的人也能知道,正是由於這個命名服務,才方便了分佈式中各個項目之間的聯繫.在SOA(Service-Oriented Architecture)框架裏面,RMI(Remote Method Invoke)框架就是經過某個服務器上的URL來獲取遠程服務器上的對象來調用服務,但到集羣和分佈式環境下,如何作到子項目之間調用的關係不會很複雜,不會到時候出現問題都不知道哪一個服務調用的哪一個,因此這裏就須要一個服務器專門替咱們管理這些服務,這樣咱們就能夠集中精力在業務處理上。Zookeeper的命名功能就是這麼一個服務器。在集羣中,相同的一個服務有不少個提供者,這些提供者啓動時,提供者的相關信息(服務接口,地址,端口等)註冊到Zookeeper中,當消費者要消費某服務的時候,從Zookeeper中獲取該服務的全部提供者的信息目錄,再根據Dubbo的負載均衡機制選擇一個提供者。

    其實從配置管理、命名服務的做用中能夠看出,Zookeeper至關於一個文件系統(相似與linux文件系統),換句話說,zookeeper是分佈式中的大腦。

  • 分佈式鎖
    分佈式鎖,又叫分佈式的同步。好比,上文中提到了Zookeeper是一個分佈式協調服務,這樣咱們就能夠利用Zookeeper來協調多個分佈式進程之間的活動。

    好比在一個分佈式環境裏,爲了提升可靠性,咱們的集羣中每臺服務器上都部署着一樣的服務。可是,一件事情若是集羣中的每一個服務器都進行的話,那相互之間就要協調,編程起來將很是複雜。而若是咱們只讓一個服務進行操做,那又存在單點。一般還有一種作法就是使用分佈式鎖,在某個時刻只讓一個服務去幹活,當這臺服務出問題的時候鎖釋放,當即fail over到另外的服務。

    不少分佈式系統都是這麼作的,這種設計有一個更好聽的名字叫Leader Election(leader選舉)。好比HBase的Master就是採用這種機制。

    但要注意的是分佈式鎖跟同一個進程的鎖仍是有區別的,因此使用的時候要比同一個進程裏的鎖更謹慎的使用。

  • 集羣管理
    在分佈式的集羣中,常常會因爲各類緣由,好比硬件故障,軟件故障,網絡問題,有些節點會進進出出。有新的節點加入進來,也有老的節點退出集羣。這個時候,集羣中其餘機器須要感知到這種變化,而後根據這種變化作出對應的決策。

    好比在一個分佈式存儲系統中,有一箇中央控制節點負責存儲的分配,當有新的存儲進來的時候咱們要根據如今集羣目前的狀態來分配存儲節點。這個時候咱們就須要動態感知到集羣目前的狀態。

    還有,好比一個分佈式的SOA架構中,服務是一個集羣提供的,當消費者訪問某個服務時,就須要採用某種機制發現 如今有哪些節點能夠提供該服務(這也稱之爲服務發現,好比Alibaba開源的SOA框架Dubbo,就採用了Zookeeper做爲服務發現的底層機制)。還有開源的Kafka隊列就採用了Zookeeper做爲Cosnumer的上下線管理。


推薦閱讀:

漫畫:什麼是ZooKeeper?



參考文檔:

ZooKeeper之(一)ZooKeeper是什麼
Zookeeper--Zookeeper是什麼
Zookeeper-Zookeeper能夠幹什麼

相關文章
相關標籤/搜索