ZooKeeper啓動數據初始化分析

在ZooKeeper服務器啓動期間,首先會進行數據初始化工作,用於將存儲在磁盤上的數據文件加載到ZooKeeper服務器內存中。

0?wx_fmt=png

初始化流程

數據初始化工作其實就是從磁盤中加載數據的過程,主要包括了從快照文件中加載快照數據的根據事務日誌進行數據訂正兩個過程。

1.初始化FileTxnSnapLog

FileTxnSnapLog是ZooKeeper事務日誌和快照數據訪問層,用於銜接上層業務與底層數據存儲。底層數據包括了事務日誌和快照兩部分,因此FileTxnSnapLog內部氛圍FileTxnLog和FileSnap的初始化,分別代表事務日誌管理器和快照數據管理器的初始化。

2.初始化ZKDatabase

接下來就開始構建內存數據庫ZKDatabase了。在初始化過程中,首先會構建一個初始化的DataTree,同時將步驟1中初始化的FileTxnSnapLog交給ZKDatabase,以便於內存數據庫能夠對事務日誌和快照數據進行訪問。

DataTree是ZooKeeper內存模型的核心模型,簡而言之就是一棵樹,保存了ZooKeeper上的所有節點信息,在每個ZooKeeper服務器內部都是單例。在ZKDatabase初始化的時候,DataTree也會進行相應的初始化工作——創建一些ZooKeeper的默認節點,包括/、/zookeeper、/zookeeper/quota三個節點的創建。

除了ZooKeeper的數據節點,在ZKDatabase的初始化階段還會創建一個用於保存所有客戶端會話超時時間的記錄器:sessionsWithTimeouts——會話超時時間記錄器。

3.創建PlayBackListener監聽器

PlayBackListener監聽器主要用來接收事務應用過程中的回調。在後面讀者會看到,在ZooKeeper數據恢復後期,會有一個事務訂正過程,在這個過程中會回調PlayBackListener監聽器來進行對應的數據訂正。

4.處理快照文件

完成內存數據庫的初始化之後,ZooKeeper就開始從磁盤中恢復數據了。在上文中我們已經提到,每一個快照數據文件中都保存了ZooKeeper服務器近似全量的數據,因此首先從這些快照文件開始加載。

5.獲取最新的100個快照文件

ZooKeeper服務器運行一段時間之後,磁盤上會保留許多快照文件。另外由於每次數據快照過程中,ZooKeeper都會將全量數據Dump到磁盤快照文件中,因此往往更新時間最晚的那個文件包含了最新的全量數據。那麼是否我們只需要這個罪行的快照文件就可以了呢?在ZooKeeper的實現中,會獲取最新的之多100個快照文件。

6.解析快照文件

獲取到這之多100個文件之後,ZooKeeper會“逐個”進行解析每個快照文件都是內存數據序列化到磁盤的二進制文件,因此在這裏需要對其進行反序列化,生成DataTree對象和sessionsWithTimeouts集合。同時在這個過程中,還會進行文件的checkSum校驗以確認快照文件的正確性。

在“逐個”解析的過程中,如果正確性校驗通過的話,呢麼通常只會解析最新的那個快照文件。換句話說,只有當最新的快照文件不可用的時候,纔會逐個進行解析,知道將這100個文件全部解析完成。如果將步驟4中獲取的所有快照文件都解析完成後還是無法完成恢復一個完整的DataTree和sessionWithTimeouts,則認爲無法從磁盤中加載數據,服務器啓動失敗。

7.獲取罪行的ZXID

完成6之後,就已經基於開招文件構建了一個完整的DataTree實例和sessionsWithTimeouts集合了。此時根據這個快照文件的文件名就可以解析出一個最新的ZXID:zxid_for_snap,它代表了ZooKeeper開始進行數據快照的時刻。

8.處理事務日誌

在經過前面7處理後,此時ZooKeeper服務器內存中已經有了一份近似全量的數據了,開始就要通過事務日誌來更新增量數據了。

9.獲取所有zxid_for_snap之後提交的事務

到這裏,我們已經獲取到了快照數據的最新ZXID。ZooKeeper中數據的快照機制決定了快照文件中並非包含了所有的事務操作。蛋是未被包含在快照中的那部分事務操作是可以我替你故宮 數據訂正來實現的。因此這裏我們只需要從事務日誌中獲取所有ZXID比步驟7中得到的zxid_for_snap大的事務操作。

10.事務應用

獲取到所有ZXID大於zxid_for_snap的事務後,將其逐個應用到之前基於快照數據文件恢復出來的DataTree和sessionsWithTimeouts中去。在事務應用的過程中,還有一個細節需要我們注意,每當有一個事務被應用到內存數據庫中,ZooKeeper同時會回調PlayBackListener監聽器,將這一事務操作記錄轉換成Proposal,保存到ZKDatabase.committedLog中,以便Follower進行快速同步。

11.獲取最新ZXID

待所有事務都被完整地應用到內存數據庫中,基本上就完成了數據的初始化過程,此時再次獲取一個ZXID,用來標識上次服務器正常運行時提交的最大事務ID。

12.校驗epoch

epoch是ZooKeeper中一個非常特別的變量,其字面意思是“時代”,在ZooKeeper中,epoch標識了當前Leader週期。每次選舉產生一個新的Leader服務器之後,就會生成一個新的cpoch。在運行期間集羣中機器互相通信的過程中,都會帶上這個epoch一確保彼此在同一個Leader週期內。

在完成數據加載後,ZooKeeper會從步驟11中確定的ZXID中解析出事務處理的Leader週期:epochOfZxid。同時會從磁盤的currentEpoch和acceptedEpoch文件中對去出上次記錄的最新的epoch值,進行校驗。

以上就是ZooKeeper服務器啓動時期的數據初始化的全過程。

更多精彩內容,歡迎關注微信公衆號:Java小筆記(ijavanote)


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