簡述Zookeeper的設計原理

Zookeeper從設計模式角度來看,是一個基於觀察者模式設計的分佈式服務管理框架,它負責存儲和管理大家都關心的數據,然後接受觀察者的註冊,一旦這些數據的狀態發生變化,Zookeeper就將負責通知已經在Zookeeper上註冊的那些觀察者做出相應的反應,從而實現集羣中類似Master/Slave管理模式。
ZooKeeper中有下面的應用:
統一命名服務(NameService)
配置管理(ConfigurationManagement)
集羣管理(GroupMembership)
共享鎖(Locks)
隊列管理


1. Zk數據模型和層級namespace
    ZK的名稱空間非常類似文件系統,名稱爲一系列的path,例如”/root/app/task”,ZK中每個node都是通過path來標識的。和文件系統不同的是,每個node可以有關聯的data,字節點也是如此,這一點可以類比爲文件系統允許path爲file或者目錄。ZK的設計是爲了存儲“協調”數據:狀態信息,配置,位置信息等;所以每個節點的data都非常的小,b-kb範圍。
    Znode維護着一個“狀態結構”(stat structure),其中包括data/ACL變更的version和時間戳,用來校驗協調數據的變更,每次znode數據變更,將會導致version號增加,每次獲取數據時,version信息也會一同獲取。
    znode中的data讀寫是原子性的,read獲取znode中關聯的所有數據,write採用replace的方式“寫入”數據,每個node都有ACL(access control list)來限制操作。
    zk還有一種node爲“臨時節點“(ephemeral node),這種節點的生命週期和相應的session一致,session失效後,節點會被刪除;臨時節點,在很多設計中具有重要的意義。
2. Watches
    Zk提供了一種”watch“的機制,client可以在znode上設置(註冊)watch。watch將會在znode節點變更時觸發,當watch觸發,client將會收到znode變更的數據消息。並且當client與server的鏈接失效後,client也會受到一個本地的通知。Watch機制爲zookeeper客戶端提供了一種”異步”以及callback方式數據獲取,客戶端可以針對自己感興趣(手動註冊的watch)或者系統事件作出相應操作.
1) 節點變更事件類型(Watcher.Event.EventType):

  • None:空事件類型,表示當前事件不是節點變更事件(極有可能是KeeperState事件)
  • NodeCreated :當註冊的watcher所關注的節點被創建時
  • NodeDeleted :當註冊的watcher所關注的節點被刪除時
  • NodeDataChanged :當註冊的watcher所關注的節點數據被update時
  • NodeChildrenChanged:當註冊的watcher所關注的節點的子節點列表有變更時.

2) Server狀態事件 (Watcher.Event.KeeperState):此類型事件爲了告知client端,此時server端狀態發生了何種變更

  •  Disconnected:當client端失去鏈接時,將會發出一個本地消息(此event非server端返回),接下來也極有可能會拋出異常(例如: ConnectionLossException, SessionExpiredException, SessionMovedException等..)
  • SyncConnected:client已經成功和ZK server建立連接,通常和Follower或者Leader建立連接.
  • AuthFailed:授權驗證失敗,比如建立連接時,鏈接重建或者session校驗時.
  • ConnectedReadOnly:client和一個read-only server建立了鏈接.可能因爲環境問題,導致當前client無法找到ZK 環境中的”Followers”或者客戶端被允許連接到Observer類型的server上.
  • Expired:當前session已經過期,其數據已經被cluster移除;這種信息是非常致命的,可能是因爲client端長時間離羣,或者ZK 集羣已經失效太久;一旦出現這個事件,唯一的辦法就是new Zookeeper(…)

    Zk非常快速而且簡單,這是它的目標,不過zk也提供了構建複雜服務的基礎,例如同步,它提供了一些保證:

  1. 順序一致性:數據的更新將按照client發送請求的順序執行。
  2. 原子性:數據更新必須有確切的結果,成功或者失敗。
  3. 一致性視圖:無論client鏈接哪個server,它將獲得一致的服務的視圖(view)。
  4. 可靠性:一旦更新被執行,它將被持久存儲。
  5. 實時性:在一定時間內,系統保證client的視圖是實時的。


3. 簡單API
    ZK的一個目標就是提供簡單的API接口,如下就是其支持的操作:(請參考:org.apache.zookeeper.Zookeeper)

  1. create:新增節點: public String create(String path,byte[] data,List<ACL> acl,CreateMode mode),同步創建;public void create(String path,byte[] data,List<ACL> acl,CreateMode mode,StringCallback cb,Object ctx),使用callback方式.
  2. delete:刪除節點
  3. exites:檢測節點是否存在 –--支持Watcher
  4. getData:獲取node上關聯的數據    ----支持Watcher
  5. setData:重置node上關聯的數據
  6. sync:同步操作,等待數據的傳播

4. 實現(implementation):


  這種可”複製“的database(解釋:我們成爲replicas database,每個ZK Server都持有一個本地的全數據鏡像數據庫副本)以data tree的方式保存在內存中,更新操作首先被持久在log中以便恢復;write在應用在內存之前首先被存儲在disk中。每個ZK server都能服務clients,client向其鏈接的server提交請求,對於read請求將會直接從本地”複製“的內存數據庫中獲取;對於更改服務狀態的write請求,將會採用agreement protocal(ZK中採用二步提交方式)。agreement protocal將會把client提交的write請求轉發給單一的server,即leader。對於其他的folower,接受leader的消息提議,同意其消息傳輸。消息層會關注leader失效時的交替以及folower和leader的數據同步。
    Zk使用自定義的原子性消息傳播機制(ZAB),因爲消息層是原子性的,ZK能夠確保本地備份不會”偏離“;當leader接受到write請求後,在應用write操作時它會”計算“系統的狀態,並以事務的方式更新狀態。
    Zk本身並不是數據庫,也不是爲數據存儲而生,所以znode上掛載的數據儘量的小,默認配置爲1M,一般我們建議此數據應該儘量的小,因爲存儲太大的數據將會造成server的操作耗時(數據庫在集羣中傳輸時間較長,網絡環境複雜也會增加數據傳輸出錯的機會),帶來請求響應延遲增大;如果你的應用需要ZK維護一些較大的數據,建議數據存儲採用其他的文件系統(或數據庫),ZK的node上只存儲文件的引用位置。

5. Sequence Nodes
    對於普通的節點創建,我們指定path,這適合一般場景;不過,在創建節點時,你可以要求ZK爲你在path的結尾追加一個自增的計數。此計數器對於其父節點而言是唯一的。計數器的格式爲%010d—10個數字前綴用0來填充:000000001,其最大值爲Integer.MAX_VALUE.

6. Zk的時間跟蹤

  1. zid:事務ID,每個數據變更操作的請求,ZK Leader都會爲其生成一個全局唯一的zid,zid也標識這請求變更的順序,如果zid1 < zid2,則認爲zid1在zid2之前發生。
  2. version number:對node的任何更新都將會導致其version增加,每個節點都有3種version: version(znode節點數據變更),cversion(子節點變更),aversion(此節點ACL變更)。
  3. Ticks:當使用多個zk server時,server需要使用ticks來聲明事件的耗時,比如狀態裝載,session過期,peer間的鏈接超時等。
  4. real time:ZK不使用絕對時間,對於數據的變更使用了時間戳。


7. ZK stat 結構

  • czxid:node創建時的zxid。
  • mzxid:znode的數據最後更新的zxid
  • ctime:此節點創建時來自epoch的time毫秒數
  • mtime:znode最後更新的毫秒數,來自epoch
  • version:znode數據更新的版本號
  • cversion:znode的字節點變更的版本號
  • aversion:znode的ACL變更的版本號
  • ephemeralOwner:臨時節點的session id,如果不是臨時節點,將爲0
  • dataLength:znode中掛載的數據的長度
  • numChildren:znode中子節點的個數

    ZK 數據結構,請參考:

    1) org.apache.zookeeper.server.DataNode; 數據的最小表示單元,每個path最終將會以DataNode來表示

    2) org.apache.zookeeper.server.DataTree; DataNode的維護關係,根據path層級關係將DataNode邏輯上存儲爲Tree

    3) org.apache.zookeeper.server.ZKDatabase: ZK本地數據庫,存儲了DataTree,ACL,Sessions列表,Wathers列表等.

    4) org.apache.zookeeper.server.SessionTracker.Session:客戶端和server的鏈接信息

    5) org.apache.zookeeper.server.persistence.FileTxnLog: ZK server所接收到的變更操作,以日誌方式存儲



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章