本文是ZooKeeper論文的閱讀筆記,ZooKeeper用於協調分佈式系統中的進程,爲分佈式系統提供消息羣發、共享寄存器、分佈式鎖這些中心化的服務。node
分佈式系統中須要的協調服務包括:配置、組成員關係、領導選舉和鎖服務。ZooKeeper並無直接提供這些服務,由於更強的原語能夠用來實現較弱的原語,ZooKeeper提供了API供開發者實現本身的原語。ZooKeeper的API操做相似文件系統的層級結構上的免等待數據對象,同時保證全部操做的客戶端先進先出和串行寫入。ZooKpeer使用管道架構實現高吞吐和低延遲,更新操做採用Zab保證線性,讀取操做在服務器本地進行,不須要肯定順序。觀察機制在數據更新以後通知客戶端,使得客戶端可以快速獲取最新數據。數據庫
ZooKeeper以庫的形式向客戶端提供API,庫也負責客戶端到ZooKeeper服務器的鏈接。ZooKeeper中的數據節點稱爲znode,以樹型命名空間組織。客戶端鏈接服務器後創建會話,經過會話句柄發送請求。bash
ZooKeeper給客戶端提供了數據對象的抽象(znode)。服務器
znode有兩種類型:架構
若是在建立文件的時候設置SEQUENTIAL
標誌,那麼會在文件名後增長一個自動增長的計數器。ZooKeeper實現了觀測(watch)機制,可以在數據對象更新後通知客戶端,觀測只會觸發一次。分佈式
數據模型:ZooKeeper中的數據模型是隻支持全量讀寫的文件系統,znode保存應用程序的抽象概念,用來存儲配置、元數據等信息。ui
會話:客戶端鏈接ZooKeeper後創建會話,會話用來標識客戶端。spa
create(path, data, flags)
:建立一個路徑爲path
的znode,將data[]
保存到其中,返回新znode的名稱,flags
用來設置znode類型:普通或者臨時,以及設置SEQUENTIAL
標誌。delete(path, version)
:若是版本匹配,刪除path
對應的znode。exists(path, watch)
:若是path
對應的znode存在,那麼返回真,不然返回假。watch
標誌讓客戶端觀測這個znode。getData(path, watch)
:返回znode對應的數據和元數據,watch
功能相似。setData(path, data, version)
:若是版本匹配,將data[]
寫入到path
對應的znode中。getChildren(path, watch)
:返回znode的子節點集合。sync(path)
:等待目前全部未決的更新,path
沒什麼用。以上所有的方法提供了阻塞版本和非阻塞版本,若是傳入版本號爲-1,那麼不進行版本檢查。.net
ZooKeeper有兩項基本的順序保證日誌
能夠舉個例子演示這兩個保證如何保障系統運行。假設一個系統選舉主節點管理其餘節點,主節點隨後須要更新一些配置,而後通知其餘節點,要求:
能夠設置一個ready
znode解決,主節點能夠在配置前刪除,完成後從新創建。當其餘節點看到ready
不存在時就不讀取配置。
可是還會存在問題:若是其餘節點看到ready
後讀取配置,可是主節點隨即刪除開始修改配置,那麼其餘節點將獲得過期的配置。這個問題能夠採用觀測機制來解決,ready
刪除後會及時通知其餘節點。
ZooKeeper兩個耐久性保證:
Lock
1 n = create(l + 「/lock-」, EPHEMERAL|SEQUENTIAL)
2 C = getChildren(l, false)
3 if n is lowest znode in C, exit
4 p = znode in C ordered just before n
5 if exists(p, true) wait for watch event
6 goto 2
複製代碼
Unlock
1 delete(n)
複製代碼
Write Lock
1 n = create(l + 「/write-」, EPHEMERAL|SEQUENTIAL)
2 C = getChildren(l, false)
3 if n is lowest znode in C, exit
4 p = znode in C ordered just before n
5 if exists(p, true) wait for event
6 goto 2
複製代碼
讀鎖之間能夠互相兼容,和寫鎖互斥。
Read Lock
1 n = create(l + 「/read-」, EPHEMERAL|SEQUENTIAL)
2 C = getChildren(l, false)
3 if no write znodes lower than n in C, exit
4 p = write znode in C ordered just before n
5 if exists(p, true) wait for event
6 goto 3
複製代碼
ready
的znode的建立,當數量到達閾值後建立。客戶端退出的時候須要等待子znode所有被刪除,一樣能夠經過刪除ready
刪除。shutdown
、migration_prohibited
是系統的配置信息,nodes
保存了屬於組成員的服務器信息,而topics
保存了負責具體話題對應的主服務器已經從服務器,另外在主節點奔潰後須要領導選舉。ZooKeeper的組件以下圖所示,ZooKeeper的數據副本保存在每個服務器上,寫操做須要經過一致性協議提交到數據庫,而讀取請求能夠直接訪問服務器本地數據庫得到。ZooKeeper在應用修改到數據庫以前會寫入到磁盤,故障後採用快照加日誌的方式進行故障。根據一致協議,寫入請求會轉發到領導(leader)節點。
請求處理器收到寫入請求以後,會將其轉換爲冪等的事務,根據請求內容計算出新的數據、版本號和時間戳,等待應用到數據庫中。
ZooKeeper使用Zab做爲原子廣播協議,使用簡單的多數認同達成一致性。Zab保證廣播發送和接受的順序是一致的,領導節點廣播以前須要確保已經收到了前一個領導的廣播。
當服務器故障後,使用週期性的快照和快照以後的日誌恢復。建立快照的時候並不須要鎖定,由於事務都是冪等的,所以再次應用已經應用的修改沒有影響。
當服務器執行一個寫入操做後,會通知觀測的客戶端並清除觀測,每一個服務器只負責通知本身鏈接的客戶端。每一個讀取請求對應着一個zxid
,對應服務器上看到的最後一個寫入事務的ID。由於讀取是在服務器本地進行,可能在讀取以前的一些寫入沒有同步到客戶端鏈接的服務器,ZooKeeper提供了sync
操做,保證sync
以後的讀取操做都可以得到發生在sync
以前的寫入結果。客戶端會從服務器獲取最新zxid
,zxid
另一個做用就是保證客戶端在切換服務器後,新服務器看到視圖不能比客戶端以前看到的視圖落後,也就是服務器zxid
不能早於客戶端的zxid
。若是檢測客戶端故障,會話是有超時時間的,客戶端在沒有活動期間也要發送心跳避免超時。