最近的項目中使用到了Zookeeper、Kafka以及Storm。仔細研究了一下,以爲這幾個開源項目對於搞分佈式的人來講是很是有用的,因此想把本身的一點心得體會總結一下,但願能對你們有所幫助。html
首先從Zookeeper開始。這一節主要是介紹一下Zookeeper的背景和架構node
zookeeper是一個開源分佈式的服務,它提供了分佈式協做,分佈式同步,配置管理等功能. 它實現的功能與google的chubby基本一致。apache
Zookeeper的官方文檔對它的設計實現有很詳細的描述,下面咱們來簡單介紹一下。session
一. Zookeeper的設計目標:數據結構
1. Simple。 ZooKeeper的命名空間組織結構相似文件系統,分佈式系統能夠基於它進行協做。Zookeeper中的每個節點都是一個znode,它相似於文件系統中的文件或文件夾。通用的文件系統通常都是設計用來存儲數據,而Zookeeper的數據都是保存在memory中的,這也意味這ZooKeeper可以有很高的throughput和很低的延遲。架構
ZooKeeper的實現主要考慮的是高性能、高可用性以及嚴格的順序訪問。 高性能意味着它能夠被用在大型的分佈式系統中;高可用性是指使用ZooKeeper集羣可以避免單點故障;嚴格的順序意味着ZooKeeper的客戶端能夠實現複雜的同步功能。分佈式
2. replicated。像不少分佈式系統同樣,ZooKeeper的數據會被拷貝到一個集羣中的多臺機器上,這些機器組成一個ZooKeeper集羣,以下圖所示:函數
組成ZooKeeper集羣服務的Server都要獲知彼此的存在。它們在內存中保存了當前ZooKeeper服務數據的最新鏡像,同時每隔一段時間會持久化保存這些鏡像數據以及transaction日誌。這些數據能夠被用來恢復ZooKeeper服務。只要大部分的ZooKeeper Server都正常,ZooKeeper服務就是可用的。oop
每一個客戶端都只會鏈接到一個ZooKeeper Server,客戶端維護了一個跟Server的TCP鏈接,能夠經過這個鏈接來發送請求、獲取數據、獲取監聽事件以及發送心跳信息。若是TCP鏈接斷掉,客戶端會嘗試鏈接到其它Server。性能
3. Ordered。ZooKeeper爲每一次update都關聯一個number,它反映了全部ZooKeeper transactions的順序。之後的操做能夠基於該順序實現更高層次的抽象,好比分佈式同步鎖等。
4. Fast。ZooKeeper在以讀操做爲主的場景中尤爲快。ZooKeeper應用能夠運行在成百上千臺機器中,當讀寫操做比爲10:1時它表現的最好。
二. ZooKeeper的數據模型和層次式的命名空間。
ZooKeeper提供的命名空間很像一個標準的文件系統,以下圖所示,它的名字是一系列由"/"分隔的路徑。ZooKeeper命名空間中的每個節點都由一個路徑指定。
三. ZooKeeper節點以及ephemeral節點
同文件系統不一樣的是,每個ZooKeeper的節點都既能夠存儲數據也能夠含有子節點。普通文件系統中,只有文件夾能夠有子文件或子目錄,文件只能用來存儲數據。因此這裏ZooKeeper就好像是文件系統容許一個文件能夠有文件夾的功能。ZooKeeper是被設計用來存儲一些協做數據的,好比說狀態信息、配置信息、位置信息等,因此一般每一個節點存儲的數據量都是很是小的(範圍在byte和kilobyte之間)。咱們用術語znode代表咱們討論的是ZooKeeper的數據節點。
znode維護了一個stat數據結構,它包含了如下信息:
當這個節點的內容或是子節點有改動時,對應的Stat中存儲的值會被更新. ZooKeeper的客戶端獲取該znode的數據時,它也同時會得到這些stat信息。
每一個命名空間對應的znode節點存儲的數據的讀和寫都是原子操做,也即讀的話會獲取當前存儲的全部數據,寫的話會用新數據覆蓋舊數據。每一個znode都有一個ACL(Access Control List)來限制誰能夠對該znode作哪些操做。
ephemeral znode是ZooKeeper中的一個重要概念,這是一中特殊的znode,只要建立它的那個session一直存在,這個znode就一直存在,一旦這個session結束了,這個znode就會被刪除。這對於分佈式系統各個組件之間相互協做是很是有用的,能夠經過註冊ephemeral 節點來標識當前各個組件的運行狀態(live or dead)。
ZooKeeper中存在下述的3種類型znode:
四. ZooKeeper的Watch
ZooKeeper中有Watch的概念, Zookeeper Watch 定義以下:
「A watch event is one-time trigger, sent to the client that set the watch, which occurs when the data for which the watch was set changes.」
Watch是由ZooKeeper的client在進行操做時設置的,全部的讀操做(getData(), getChildren(), and exists())均可以選擇設置watch。在我看來,watch能夠理解爲一個分佈式的回調,當client關心的znode發生變化時,zookeeper將會把消息傳回到client,並致使client的消息處理函數獲得調用. 後面咱們會詳細介紹ZooKeeper的Watch的實現機制。
五. ZooKeeper的保證
ZooKeeper很是快而且很是簡單,因爲它的目標是成爲構建複雜系統的基石(好比說同步系統),它提供了一系列的保證,它們是:
1. 順序的一致性。 一個Client所發送的全部更新的執行順序跟它們的發送順序是一致的。
2. 原子性。更新操做要麼成功要麼失敗,不存在部分紅功的狀況。
3. 單一系統鏡像。在一個ZooKeeper集羣中,一個Client不論連接到哪一個Server上,它看到的ZooKeeper系統的狀態/視圖應該是相同的。
4. 可靠性。 一旦一個更新操做執行成功,這個更改就會一直存在直到有一個client又對它進行了更改/覆蓋。
5. 時效性。在必定的時間限制範圍內,確保全部client看到的ZooKeeper系統的數據是最新的。
但願看完這一章以後,你們會對ZooKeeper有一個基礎的印象,後面的章節會詳細介紹ZooKeeper中設計和實現。