前段時間公司hadoop集羣宕機,發現是namenode 磁盤滿了。。清理出部分空間後,重啓集羣時,重啓失敗。node
又發現集羣Secondary namenode 服務也偏偏壞掉,致使全部的操做log持續寫入edits.new 文件,等集羣宕機的時候文件大小已經達到了喪心病狂的70G+..重啓集羣報錯 加載edits文件失敗。分析加載文件報錯緣由是磁盤不足致使最後寫入的log只寫入一半就宕機了。因爲log不完整,hadoop再次啓動加載edits文件時讀取文件報錯。因爲edits.new 文件過大,存儲了好多操做log,因此必需要對其進行修復。ios
嘗試刪除文件的最後幾行,結果仍是報錯。因而查看源碼對edits 文件結構進行分析發現是二進制格式,首行爲版本號,而後是hadoop運行過程當中的log記錄內容,由操做碼 +長度(非必須)+其餘項組成。apache
報錯位置在源碼中的方法爲org.apache.hadoop.hdfs.server.namenode.FSEditLog.loadFSEdits(EditLogInputStream edits)方法中讀取文件最後位置時由於缺乏部分數據報錯, 因此把這部分代碼單獨拿出來,去掉業務操做部分,只留讀取過程,記錄異常以前的文件長度len,而後將0到len 這部分的內容複製出來成新的edits文件。啓動hadoop集羣,成功!函數
NameNode函數裏調用FSNamesystemm讀取dfs.namenode.name.dir和dfs.namenode.edits.dir構建FSDirectory。oop
FSImage類recoverTransitionRead和saveNameSpace分別實現了元數據的檢查、加載、內存合併和元數據的持久化存儲。spa
saveNameSpace將元數據寫入到磁盤,具體操做步驟:首先將current目錄重命名爲lastcheckpoint.tmp;而後在建立新的current目錄,並保存文件;最後將lastcheckpoint.tmp重命名爲privios.checkpoint.日誌
checkPoint的過程:Secondary NameNode會通知nameNode產生一個edit log文件edits.new,以後全部的日誌操做寫入到edits.new文件中。接下來Secondary NameNode會從namenode下載fsimage和edits文件,進行合併產生新的fsimage.ckpt;而後Secondary會將fsimage.ckpt文件上傳到namenode。最後namenode會重命名fsimage.ckpt爲fsimage,edtis.new爲edits;server
PS:
內存
最新的CDH版本的hadoop 集羣啓動能夠對edits文件進行recover操做,跳過報錯loghadoop