1. 程式人生 > 其它 >大資料開發之zookeeper的資料與儲存

大資料開發之zookeeper的資料與儲存

一、記憶體資料

zk的資料模型是樹結構,在記憶體資料庫中,儲存了整棵樹的內容,包括所有的節點路徑、節點資料、ACL資訊,zk會定時將這個資料儲存到磁碟上

1.1 DataTree

DataTree是記憶體資料儲存的核心,是一個樹結構,代大資料培訓表了記憶體中一份完整的資料。DataTree不包含任何與網路、客戶端連線及請求處理相關的業務邏輯,是一個獨立的元件。

1.2 DataNode

DataNode是資料儲存的最小單元,其內部除了儲存了結點的資料內容、ACL列表、節點狀態之外,還記錄了父節點的引用和子節點列表兩個屬性,其也提供了對子節點列表進行操作的介面。

1.3 ZKDatabase

zk的記憶體資料庫,管理zk的所有會話、DataTree儲存和事務日誌。ZKDatabase會定時向磁碟dump快照資料,同時在zk啟動時,會通過磁碟的事務日誌和快照檔案恢復成一個完整的記憶體資料庫。

二、事務日誌

2.1 日誌寫入

FileSnap負責維護快照資料對外的介面,包括快照資料的寫入和讀取等,將記憶體資料庫寫入快照資料檔案其實是一個序列化過程。針對客戶端的每一次事務操作,zk都會將他們記錄到事務日誌中,同時也會將資料變更應用到記憶體資料庫中,zk在進行若干次事務日誌記錄後,將記憶體資料庫的全量資料Dump到本地檔案中,這就是資料快照。其步驟如下;

1.確定是否需要進行資料快照。每進行一次事務日誌記錄之後,zk都會檢測當前是否需要進行資料快照,考慮到資料快照對於zk機器的影響,需要儘量避免zk叢集中的所有機器在同一時刻進行資料快照。採用過半隨機策略進行資料快照操作。

2.切換事務日誌檔案。表示當前的事務日誌已經寫滿,需要重新建立一個新的事務日誌。

3.建立資料快照非同步執行緒。建立單獨的非同步執行緒來進行資料快照以避免影響zk主流程。

4.獲取全量資料和會話資訊。從ZKDatabase中獲取到DataTree和會話資訊。

5.生成快照資料檔名。zk根據當前已經提交的最大ZXID來生成資料快照檔名。

6.資料序列化。首先序列化檔案頭資訊,然後再對會話資訊和DataTree分別進行序列化,同時生成一個Checksum,一併寫入快照資料檔案中去。

四、資料初始化

在zk伺服器啟動期間,首先會進行資料初始化工作,用於將儲存在磁碟上的資料檔案載入到zk伺服器記憶體中。

4.1 初始化流程

zk的初始化過程如下圖所示;

資料的初始化工作是從磁碟上載入資料的過程,主要包括了從快照檔案中載入快照資料和根據實物日誌進行資料修正兩個過程。

  1. 初始化FileTxnSnapLog和
    FileTxnSnapLog是zk事務日誌和快照資料訪問層,用於銜接上層業務和底層資料儲存,底層資料包含了事務日誌和快照資料兩部分。FileTxnSnapLog中對應FileTxnLog和FileSnap。
  2. 初始化ZKDatabase。首先構建DataTree,同時將FileTxnSnapLog交付ZKDatabase,以便記憶體資料庫能夠對事務日誌和快照資料進行訪問。在ZKDatabase初始化時,DataTree也會進行相應的初始化工作,如建立一些預設結點如/、/zookeeper、/zookeeper/quota三個節點。
  3. 建立PlayBackListener。其主要用來接收事務應用過程中的回撥,在zk資料恢復後期,會有事務修正過程,此過程會回撥PlayBackListener來進行對應的資料修正。
  4. 處理快照檔案。此時可以從磁碟中恢復資料了,首先從快照檔案開始載入。
  5. 獲取最新的100個快照檔案。更新時間最晚的快照檔案包含了最新的全量資料。這裡的100是硬編碼,無引數配置。
  6. 解析快照檔案。逐個解析快照檔案,此時需要進行反序列化,生成DataTree和sessionsWithTimeouts,同時還會校驗Checksum及快照檔案的正確性。對於100個快找檔案,如果正確性校驗通過時,通常只會解析最新的那個快照檔案。只有最新快照檔案不可用時,才會逐個進行解析,直至100個快照檔案全部解析完。若將100個快照檔案解析完後還是無法成功恢復一個完整的DataTree和sessionWithTimeouts,此時伺服器啟動失敗。
  7. 獲取最新的ZXID。此時根據快照檔案的檔名即可解析出最新的ZXID:zxid_for_snap。該ZXID代表了zk開始進行資料快照的時刻。
  8. 處理事務日誌。此時伺服器記憶體中已經有了一份近似全量的資料,現在開始通過事務日誌來更新增量資料。
  9. 獲取所有zxid_for_snap之後提交的事務。此時,已經可以獲取快照資料的最新ZXID。只需要從事務日誌中獲取所有ZXID比步驟7得到的ZXID大的事務操作。

10.事務應用。獲取大於zxid_for_snap的事務後,將其逐個應用到之前基於快照數 據檔案恢復出來的DataTree和sessionsWithTimeouts。每當有一個事務被應用 到記憶體資料庫中後,zk同時會回撥PlayBackListener,將這事務操作記錄轉換成 Proposal,並儲存到ZKDatabase的committedLog中,以便Follower進行快速 同步。

11.獲取最新的ZXID。待所有的事務都被完整地應用到記憶體資料庫中後,也就基本 上完成了資料的初始化過程,此時再次獲取ZXID,用來標識上次伺服器正常執行 時提交的最大事務ID。

12.校驗epoch。epoch標識了當前Leader週期,叢集機器相互通訊時,會帶上這個 epoch以確保彼此在同一個Leader週期中。完成資料載入後,zk會從步驟11中 確定ZXID中解析出事務處理的Leader週期:epochOfZxid。同時也會從磁碟的 currentEpoch和acceptedEpoch檔案中讀取上次記錄的最新的epoch值,進行 校驗。

五、資料同步

5.1 同步流程

整個叢集完成Leader選舉後,Learner會向Leader進行註冊,當Learner向Leader完成註冊後,就進入資料同步環節,同步過程就是Leader將那些沒有在Learner伺服器上提交過的事務請求同步給Learner伺服器,大體過程如下

  1. 獲取Learner狀態。在註冊Learner的最後階段,Learner伺服器會發送給Leader伺服器一個ACKEPOCH資料包,Leader會從這個資料包中解析出該Learner的currentEpoch和lastZxid。
  2. 資料同步初始化。首先從zk記憶體資料庫中提取出事務請求對應的提議快取佇列proposals,同時完成peerLastZxid(該Learner最後處理的ZXID)、minCommittedLog(Leader提議快取佇列commitedLog中最小的ZXID)、maxCommittedLog(Leader提議快取佇列commitedLog中的最大ZXID)三個ZXID值的初始化。
    對於叢集資料同步而言,通常分為四類,直接差異化同步(DIFF同步)、先回滾再差異化同步(TRUNC+DIFF同步)、僅回滾同步(TRUNC同步)、全量同步(SNAP同步),在初始化階段,Leader會優先以全量同步方式來同步資料。同時,會根據Leader和Learner之間的資料差異情況來決定最終的資料同步方式。直接差異化同步(DIFF同步,peerLastZxid介於minCommittedLog和maxCommittedLog之間)。Leader首先向這個Learner傳送一個DIFF指令,用於通知Learner進入差異化資料同步階段,Leader即將把一些Proposal同步給自己,針對每個Proposal,Leader都會通過傳送PROPOSAL內容資料包和COMMIT指令資料包來完成,
    先回滾再差異化同步(TRUNC+DIFF同步,Leader已經將事務記錄到本地事務日誌中,但是沒有成功發起Proposal流程)。當Leader發現某個Learner包含了一條自己沒有的事務記錄,那麼就需要該Learner進行事務回滾,回滾到Leader伺服器上存在的,同時也是最接近於peerLastZxid的ZXID。· 僅回滾同步(TRUNC同步,peerLastZxid大於maxCommittedLog)。Leader要求Learner回滾到ZXID值為maxCommittedLog對應的事務操作。· 全量同步(SNAP同步,peerLastZxid小於minCommittedLog或peerLastZxid不等於lastProcessedZxid)。Leader無法直接使用提議快取佇列和Learner進行同步,因此只能進行全量同步。Leader將本機的全量記憶體資料同步給Learner。Leader首先向Learner傳送一個SNAP指令,通知Learner即將進行全量同步,隨後,Leader會從記憶體資料庫中獲取到全量的資料節點和會話超時時間記錄器,將他們序列化後傳輸給Learner。Learner接收到該全量資料後,會對其反序列化後載入到記憶體資料庫中。

原創作者:徐賣狼