1. 程式人生 > >關於namenode、datanode和secondarynamenode的互動過程

關於namenode、datanode和secondarynamenode的互動過程

元資料是儲存在namenode中的,這些元資料包括檔名、目錄名,檔案目錄從屬關係、檔案大小,檔案與塊對應關係,塊所對應的節點等;namenode會將這些元資料資訊儲存在硬碟上,對應的名字是fsimage_txid(即類似這種:fsimage_000000000000003210),以備下次啟動時,可以及時獲取到整個hdfs檔案系統的重要資訊;除了這個檔案,還有一個檔案edits(或者叫editlog,對應的名字格式:edit_0000000000000xxxx-000000000000xxx+1,由於此檔案儲存hdfs的所有動作,儲存資料量較大,因此通常會分成多個檔案儲存)檔案,這個檔案記錄了namenode(以及客戶端)和datanode互動的所有動作,如果說fsimage檔案是地理緯度,則edits檔案是時間維度,也就是說,fsimage檔案+edits檔案=hdfs在某一時刻的快照。

當hdfs重新啟動時,必須獲得hdfs關閉前的狀態,而這個狀態自然是記錄在fsimage和edits檔案中的,因此需要將fsimage和edits中儲存的資訊載入入namenode的記憶體,其方式是先將fsimage載入,然後逐條執行edits中的指令,這樣看好像解決了重啟丟失資料的問題,但仍然有其它問題,hdfs叢集通常是長期不關機的,這回造成edits檔案無限變大,如果經過了很長時間後,需要重啟一次,再像之前那樣載入fsimage特別是edits檔案,會出現啟動時間過長的問題.....三五個小時,甚至整天的時間......

解決這個問題的關鍵在於怎樣在不停止hdfs服務的情況下縮小edits檔案,且又要保證資料完整性!目前,hadoop是使用secondarynamenode來解決這個問題的,見下圖(不好意思,摘自網上,自己畫圖水平實在太爛....):

在上圖中,首先,namenode將自己的edits檔案重新命名為edits-new;然後在滿足一些條件的情況下(這些條件包括:時間“預設一個小時,由hdfs-default.xml中的dfs.namenode.checkpoint.preiod引數指定”;次數“預設一百萬次,有hdfs-default.xml的dfs.namenode.checkpoint.txns引數指定”)secondarynamenode通過HTTP的GET請求方式去獲取namenode上的fsimage和edits檔案;第三,在secondarynamenode中將edits和fsimage進行合併(合併過程:snd載入fsimage,執行edits中的操作,然後重新生成一個新的fsimage,並重命名為fsimage_ckpd_txid);第四,通過HTTP的POST方式將合併後的fsimage上傳到namenode下,重新命名為fsimage_txid,將edits_new檔案重新命名為edits_txid;最後,namenode載入新的fsimage,在fstime檔案中記錄下checkpoint發生的時間點。

另外,上圖中注意紅框部分,並不是把edits檔案直接更新到fsimage中,而是secondarynamenode先載入下載下來的fsimage,然後逐條執行edits中的記錄,最後重新生成一個新的fsimage。