記一次Hadoop1.0.4集群的事故

由于歷史原因,公司內(nèi)部還在使用hadoop1.0.4版本的集群,而且上面運(yùn)行的任務(wù)還挺多。當(dāng)初開發(fā)這套系統(tǒng)的員工幾乎都離職了,所以這塊成了雞肋。撤掉吧,上面還有好的用戶;遷移吧,涉及的東西太多,影響比較大。所以這套系統(tǒng)就只能一直這樣維護(hù)著。

終于在一次集群的大事故中,讓大家認(rèn)識(shí)到,再也不能用hadoop1.0集群了。

一、問題的原因

Hadoop1.0的HDFS元數(shù)據(jù)是存放在fsimage中的,編輯日志存放在edits;SecondaryNameNode節(jié)點(diǎn)負(fù)責(zé)把edits日志合并到fsimage中,用于數(shù)據(jù)恢復(fù)。當(dāng)遇到edits日志中存在異常的時(shí)候,元數(shù)據(jù)不再往edits文件中寫,而是寫入edits.new文件中。當(dāng)發(fā)現(xiàn)這個(gè)問題的時(shí)候,就需要在hdfs的安全模式下,使用以下命令進(jìn)行恢復(fù)

hadoop dfsadmin -saveNamespace

但是在沒恢復(fù)之前,如果重啟namenode節(jié)點(diǎn),問題就大了。我們這邊由于某個(gè)mr采用多路徑輸出,把中文輸出到文件路徑中了,導(dǎo)致在元數(shù)據(jù)中存放了亂碼,啟動(dòng)namenode的時(shí)候,fsimage一直檢查不通過,異常如下:

ERROR org.apache.hadoop.hdfs.server.namenode.NameNode: java.io.IOException: Found lease for non-existent file /data/houraggregate/eventself_day/2017/05/01/14/output/_temporary/_attempt_201602020826_208092_r_000006_0/part-r-00006-DESelf_Coi#@$%^Pd
    at org.apache.hadoop.hdfs.server.namenode.FSImage.loadFilesUnderConstruction(FSImage.java:1440)
    at org.apache.hadoop.hdfs.server.namenode.FSImage.loadFSImage(FSImage.java:986)
    at org.apache.hadoop.hdfs.server.namenode.FSImage.loadFSImage(FSImage.java:830)
    at org.apache.hadoop.hdfs.server.namenode.FSImage.recoverTransitionRead(FSImage.java:377)
    at org.apache.hadoop.hdfs.server.namenode.FSDirectory.loadFSImage(FSDirectory.java:100)
    at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.initialize(FSNamesystem.java:388)
    at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.<init>(FSNamesystem.java:362)
    at org.apache.hadoop.hdfs.server.namenode.NameNode.initialize(NameNode.java:276)
    at org.apache.hadoop.hdfs.server.namenode.NameNode.<init>(NameNode.java:496)
    at org.apache.hadoop.hdfs.server.namenode.NameNode.createNameNode(NameNode.java:1279)
    at org.apache.hadoop.hdfs.server.namenode.NameNode.main(NameNode.java:1288)

二、處理過程

既然是edit文件出異常,就應(yīng)該修復(fù)該文件。查看資料是可以通過以下命令把edit這個(gè)二進(jìn)制文件解析成xml文件的

hdfs oev -i edits -o edits.xml //解析edits文件
hdfs oiv -i fsimage -o fsimage.xml //解析fsimage文件

解析完成后通過以下命令重新轉(zhuǎn)回二進(jìn)制文件

hdfs oev -i edits.xml -o edits -p binary //轉(zhuǎn)換xml文件成edits文件
hdfs oiv -i fsimage.xml-o fsimage -p binary //轉(zhuǎn)換xml文件成fsimage文件

由于系統(tǒng)是hadoop1.0.4所以不存在 hdfs 這個(gè)命令,只好把文件拷貝到hadoop2.6.0上進(jìn)行操作。

打開轉(zhuǎn)換后的xml文件,把存在亂碼的Recode標(biāo)簽內(nèi)的記錄都刪除掉,然后在轉(zhuǎn)換為二進(jìn)制文件。

當(dāng)解析 image 文件的時(shí)候,發(fā)現(xiàn)解析不了,查看資料才發(fā)現(xiàn),原來fsimage文件是與hadoop版本一一對(duì)應(yīng)的。

所以上面所做的所有工作都是無效的。

后面想到,能不能通過查看hadoop寫fsimage文件的過程,然后反過來解析呢?但是這樣處理,會(huì)耗費(fèi)大量的時(shí)間去閱讀源碼,實(shí)際情況是不允許的。轉(zhuǎn)念一想,能不能把判斷亂碼的代碼修改為,如果遇到就跳過呢?

通過查看異常的堆棧,找到是 FSImage 類的以下代碼報(bào)出的異常

for (int i = 0; i < size; i++) {
      INodeFileUnderConstruction cons = readINodeUnderConstruction(in);

      // verify that file exists in namespace
      String path = cons.getLocalName();
      
      INode old = fsDir.getFileINode(path);
      if (old == null) {
        // 從此處報(bào)出異常
        throw new IOException("Found lease for non-existent file " + path);
      }
      if (old.isDirectory()) {
        throw new IOException("Found lease for directory " + path);
      }
      INodeFile oldnode = (INodeFile) old;
      fsDir.replaceNode(path, oldnode, cons);
      fs.leaseManager.addLease(cons.clientName, path); 
    }

把代碼修改如下:

for (int i = 0; i < size; i++) {
      INodeFileUnderConstruction cons = readINodeUnderConstruction(in);

      // verify that file exists in namespace
      String path = cons.getLocalName();
      
      // 添加判斷,把存在異常的路徑過濾掉
      if (path.contains("_temporary")){
          continue;
      }
      
      INode old = fsDir.getFileINode(path);
      if (old == null) {
        throw new IOException("Found lease for non-existent file " + path);
      }
      if (old.isDirectory()) {
        throw new IOException("Found lease for directory " + path);
      }
      INodeFile oldnode = (INodeFile) old;
      fsDir.replaceNode(path, oldnode, cons);
      fs.leaseManager.addLease(cons.clientName, path); 
    }

然后編譯FSImage類,打包到hadoop-core-1.0.4.jar中,放入hadoop1.0.4 namenode節(jié)點(diǎn)的對(duì)應(yīng)目錄下,重啟namenode進(jìn)程,終于能正常啟動(dòng)了。

三、總結(jié)

1、不能在edits.new存在的情況下,重啟namenode進(jìn)程

2、hdfs中的路徑不能存在亂碼,最后就用字母數(shù)字下劃線這些比較通用的字符來做路徑

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容