美文网首页
记一次Hadoop1.0.4集群的事故

记一次Hadoop1.0.4集群的事故

作者: yannhuang | 来源:发表于2017-06-27 16:39 被阅读50次

由于历史原因,公司内部还在使用hadoop1.0.4版本的集群,而且上面运行的任务还挺多。当初开发这套系统的员工几乎都离职了,所以这块成了鸡肋。撤掉吧,上面还有好的用户;迁移吧,涉及的东西太多,影响比较大。所以这套系统就只能一直这样维护着。

终于在一次集群的大事故中,让大家认识到,再也不能用hadoop1.0集群了。

一、问题的原因

Hadoop1.0的HDFS元数据是存放在fsimage中的,编辑日志存放在edits;SecondaryNameNode节点负责把edits日志合并到fsimage中,用于数据恢复。当遇到edits日志中存在异常的时候,元数据不再往edits文件中写,而是写入edits.new文件中。当发现这个问题的时候,就需要在hdfs的安全模式下,使用以下命令进行恢复

hadoop dfsadmin -saveNamespace

但是在没恢复之前,如果重启namenode节点,问题就大了。我们这边由于某个mr采用多路径输出,把中文输出到文件路径中了,导致在元数据中存放了乱码,启动namenode的时候,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文件出异常,就应该修复该文件。查看资料是可以通过以下命令把edit这个二进制文件解析成xml文件的

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

解析完成后通过以下命令重新转回二进制文件

hdfs oev -i edits.xml -o edits -p binary //转换xml文件成edits文件
hdfs oiv -i fsimage.xml-o fsimage -p binary //转换xml文件成fsimage文件

由于系统是hadoop1.0.4所以不存在 hdfs 这个命令,只好把文件拷贝到hadoop2.6.0上进行操作。

打开转换后的xml文件,把存在乱码的Recode标签内的记录都删除掉,然后在转换为二进制文件。

当解析 image 文件的时候,发现解析不了,查看资料才发现,原来fsimage文件是与hadoop版本一一对应的。

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

后面想到,能不能通过查看hadoop写fsimage文件的过程,然后反过来解析呢?但是这样处理,会耗费大量的时间去阅读源码,实际情况是不允许的。转念一想,能不能把判断乱码的代码修改为,如果遇到就跳过呢?

通过查看异常的堆栈,找到是 FSImage 类的以下代码报出的异常

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) {
        // 从此处报出异常
        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节点的对应目录下,重启namenode进程,终于能正常启动了。

三、总结

1、不能在edits.new存在的情况下,重启namenode进程

2、hdfs中的路径不能存在乱码,最后就用字母数字下划线这些比较通用的字符来做路径

相关文章

  • 记一次Hadoop1.0.4集群的事故

    由于历史原因,公司内部还在使用hadoop1.0.4版本的集群,而且上面运行的任务还挺多。当初开发这套系统的员工几...

  • HBase的分布式集群安装

    HBase的分布式集群安装 这里安装的集群使用的是hadoop1.0.4版本,所以使用的hbase版本是0.94....

  • 2019-03-29

    记一次16个小时的 beta 环境 zk 集群故障 最近公司的 beta 环境 zk 集群经历了一次大震荡,16个...

  • 记一次事故

    在湖南省,某市,发生过这样一起交通事故。 那天刚好下着小雨,一位母亲和她的孩子有说有笑地走在马路边。孩子还小,...

  • 第七十一篇:海恩法则

    每一次严重事故的背后,必然有29次轻微事故和300起未遂先兆以及1000起事故隐患。 希望日常生活中能用心观察、记...

  • 记一次家庭事故

    2019年7月28日,11点左右,接到我的伯妈打来的电话,内容是我奶奶在地里搬苞谷倒在地里起不来了,整个人处于人事...

  • 记一次追尾事故

    出了车祸,三车追尾,我的全责。 在撞上去的那一瞬间,脑中真的一片空白,什么也想不到了。意外的是车居然没有熄火,看来...

  • 记一次行车事故

    今天从临武回家,到村口已经是晚上七点二十,天已经渐渐暗下来。但还需前往万水取快递,行车至村子另一路口处,有一辆白色...

  • 记一次上线事故

    新年第三周,解答知乎的问答了解了二叉树、尝试跑了flutter demo,却忘了最重要的网络基础的学习。 关键词 ...

  • 记一次线上事故

    今天服务忽然炸了,log没有记录,服务一直重启导致数据库压力暴增。

网友评论

      本文标题:记一次Hadoop1.0.4集群的事故

      本文链接:https://www.haomeiwen.com/subject/uueecxtx.html