分享

关于hadoop中datanode节点不同的dfs.data.dir之间数据均衡问题

when30 发表于 2013-10-25 10:42:58 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 2 7207
:集群中的存储数据增大,导致datanode的空间都快占满了(以前的dfs.data.dir=/data/hdfs/dfs/data),机器的硬盘监控程序不停的报警 。
         给每台机器加了一倍的存储硬盘(新的dfs.data.dir=/data/hdfs/dfs/data,/data/hdfs/dfs/data2    新的硬盘挂载在/data/hdfs/dfs/data2),但是现在的来了,以前装数据的那块盘还是满的,仍然在报警,怎么把数据均衡到这两块盘上面 吗?吗?
解决:移动其中一个文件夹的数据(其实也就是block)到另外一个文件加 。
原理:hdfs中文件的inode文件树信息以及每个文件对应的block信息存储在NN中的,每个block存储在那几台DN机器上是在集群启动时候,由每台datanode根据自身所拥有的block上报上去的。 datanode在启动时候,也是扫描自身dfs.data.dir的各个文件夹下的current(前提是这个目录的VERSION等必要信息文件时存在的,这个目录是合法的)目录,然后将下面存在block信息(有哪些block,存在那个文件夹下)上报到NN (详细参见DataNode的FSDataset代码)。
操作:
1、停止集群 。
2、修改dfs.data.dir的配置 。
3、启动集群(先只启动hdfs),该步的目的是:让DataNode去格式化/data/hdfs/dfs/data2,填充其中的一些系统信息文件(例如:current  ,current/VERSION,detach ,storage等)。
5、使用http://namenodeAddress:50070/fsck来检查文件系统,并记录下结果,以便与修改后进行fsck比较,看文件系统是否健全 。
4、停止集群 。
5、进入/data/hdfs/dfs/data/current 目录,将其中一些较大的子文件夹(如果是系统生成的名字一般是subdir**)mv到/data/hdfs/dfs/data2/current 下 。
6、启动集群 (先是hdfs,好做检查) 。
7、再次执行http://namenodeAddress:50070/fsck命令,将结果与前一次比较,没出的话,应该是一样的 。
PS:在dev机器上做了相应的实验,做之前将dev的数据文件备份,现在启动dev的集群,已经跑了一段时间,并没有出现 。
源代码部分:
   在DataNode中,每个dfs.data.dir的文件夹对应的是一个FSDir类,而其文件下的每一个子文件夹对应一个FSDir ,每次DataNode启动时,会对每一个dfs.data.dir的文件启动一个FSDir对象,让后其在构造函数中会统计该FSDir下存储哪些block ,也既是每个block存在那个文件夹只有在DataNode启动时扫描自己的dfs.data.dir是才知道,这也是本次修改的原理 。
[ol]
  •     public FSDir(File dir)
  •       throws IOException {
  •       this.dir = dir;
  •       this.children = null;
  •       //文件夹不存在则创建文件夹
  •       //不会覆盖或删除已经存在的文件夹,为手工移动block提供了便利性
  •       if (!dir.exists()) {                                                                                                                                                                                                
  •         if (!dir.mkdirs()) {
  •           throw new IOException("Mkdirs failed to create " +
  •                                 dir.toString());
  •         }
  •       } else {
  •         File[] files = dir.listFiles();
  •         int numChildren = 0;
  •         //自检查文件夹个数(子FSDir的个数)和文件(block个数)
  •         for (int idx = 0; idx  0) {
  •           children = new FSDir[numChildren];
  •           int curdir = 0;
  •           for (int idx = 0; idx 复制代码
    其往FSDir中添加block的代码:


    [ol]
  • /**
  •      * //所作的事情:将在tmp中的block文件以及其meta文件mv(重命名)到current中
  •      * 第一次调用的形式是:先调用 File file = addBlock(b, src, false, false) ,再调用addBlock(b, src, true, true)      
  •      * boolean createOk :  是否需要在子FSDir中创建子子FSDir,先不创建的添加,若是不行(子目录存放的block也满了),再允许子目录创建子子目录 。
  •      * boolean resetIdx : 当存储需要在子目录中时候,每次存储完都有一个lastChildIdx表明上次存在哪个文件夹下:设置为true表示下次会在随机选一个,false表示下次还接着上次的来存
  •      */
  •     private File addBlock(Block b, File src, boolean createOk,
  •                           boolean resetIdx) throws IOException {
  •       //本层目录未满,这直接将block添加在本目录
  •       if (numBlocks = 0 && children != null) {
  •         //Check if any child-tree has room for a block.
  •         for (int i=0; i 复制代码
    maxBlocksPerDir由dfs.datanode.numblocks确定,默认是64 ,含义是每个FSDir中最多存储多少个block ,最多存储多少个子
    FSDir
    贴出以上代码主要是刚开始怕DataNode有一套自己的机制,会把你添加进去的文件(夹)清除掉,或者是把不符合规则的子文件夹(一般的是当建立子文件夹是会一次性建立subdir0--subdir63 这64个文件夹,代码见第二部分代码)清除掉 ,但是后来看过代码后发现也没这些逻辑 。
  • 已有(2)人评论

    跳转到指定楼层
    cryst2l 发表于 2013-10-25 10:42:58
    did you run HDFS balancer? The balancer will try to move blocks from a host almost full to another host with more free space.
    回复

    使用道具 举报

    yuanqingyu0123 发表于 2013-10-25 10:42:58
    回复 2# brandon
    是的,我使用了balancer,但是在同一台机器datanode上,dfs.data.dir定义的多个文件夹下不起平衡的作用, 我认为balancer只是用于平衡多个DN间的负载不均衡的 。
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    关闭

    推荐上一条 /2 下一条