Google的三篇論文影響了很多很多人,也影響了很多很多系統。這三篇論文一直是分布式領域傳閱的經典。根據MapReduce,於是我們有了Hadoop;根據GFS,於是我們有了HDFS;根據BigTable,於是我們有了HBase。而在這三篇論文里都提及Google的一個lock service---Chubby,哦,於是我們有了Zookeeper。
隨着大數據的火熱,Hxx們已經變得耳熟能詳,現在作為一個開發人員如果都不知道這幾個名詞出門都好像不好意思跟人打招呼。但實際上對我們這些非大數據開發人員而言,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到底能干些什么。