hadoop hdfs总结 NameNode部分 2

二、BlocksMap部分

     在NameNode 介绍1中,说明了INode部分,INode抽象了NameNode中文件属性,与之相同的是Block部分,Block是对NameNode中实际存储的Block的抽象。这两部分构成了NameNode的最重要的元信息。

     Block继承结构为基类Block,BlockInfo继承自Block,是BlocksMap的内部类,BlocksMap是BlockInfo的一个hashmap存储。

     首先说明一下BlockInfo的意义,在hdfs中,数据实际上是存储在DataNodes中的Block,每个Block是64M(可配置),文件较大时对应需要多个Block进行存储,同时为了安全性每个Block进行了多份备份,存储在不同的DataNodes中(NameNode中算法分配)。INodeFile中有protected BlockInfo blocks[] 表示该INodeFile由几个Block组成。而BlockInfo内部结构则表示了该Block备份到了哪几个DataNodes中,同时BlockInfo还有一个三元组结构,类似于数据结构中的双向链表,除了保存该Block存储在哪个DataNode中还保存了该DataNode存储的其他BlockInfo引用。引入三元组的原因是除了要得到INodeFile--->Blocks的映射,和Block--->DataNodes的映射外,还需要得到DataNodes--->Blocks的映射。一旦DataNodes故障或者下线,能够将其对应的所有Block进行备份。

     详细说明各个结构:

     1、Block

     Block需要在NameNode,DataNodes间进行传输,所以进行了序列化。主要属性为     

  private long blockId;
  private long numBytes;
  private long generationStamp;

  其他方法都是围绕着三个属性进行。在DataNodes中block存储为blk_$blockId的形式。generationStamp是为了进行append过程或recovery过程设置的time stamp。

     2、BlockInfo

     BlockInfo是BlocksMap的内部类,继承了Block类。属性为     

  private INodeFile inode;
  private Object[] triplets;

  inode是该BlockInfo对应的INodeFile,triplets就是前面说过的三元组。它表示为该BlockInfo被复制在多个DataNodes中,结构为triplets[3*i]表示同一个Block复制到的某个DataNode,triplets[3*i+1]和triplets[3*i+2]表示该DataNodes对应的其它Block,可以认为是前驱和后继Block。DataNodeDescriptor有一个头结点的引用,这个会在后面分析说到。

      一些重要的方法是:

     (1)DatanodeDescriptor getDatanode(int index)

      获得第i个DataNode。

     (2)BlockInfo getPrevious(int index)    BlockInfo getNext(int index)

      获得第i个DataNode的前驱BlockInfo和后继BlockInfo。

     (3)void setPrevious(int index, BlockInfo to)   void setNext(int index, BlockInfo to)

      设置该第i个DataNode对应该BlockInfo的前驱和后继BlockInfo结点。

     (4)private int getCapacity()

      该Block存储在多少个DataNode中。

     (5)int numNodes()

      获得该Block对应的有效的DataNodes个数。

     (6)private int ensureCapacity(int num)

      加入新的DataNodes,如setReplication由3变为7,需要将block复制到其他DataNodes节点中。主要代码为      

Object[] old = triplets;
      triplets = new Object[(last+num)*3];
      for(int i=0; i < last*3; i++) {
        triplets[i] = old[i];
      }

  由于DataNodes个数不会太多,所以这种复制效率是可以接受的。

    (7)BlockInfo listInsert(BlockInfo head, DatanodeDescriptor dn)

     DataNodeDerscriptor中维护了一个头结点,将this引用加入到list中。

    (8)BlockInfo listRemove(BlockInfo head, DatanodeDescriptor dn)

     将this引用从DatanodeDescriptor中的链表(三元组)中删除。

    3、BlocksMap

     BlocksMap将BlockInfo wrapper。     

private Map<BlockInfo, BlockInfo> map;

   重要方法是:

    (1)

private BlockInfo checkBlockInfo(Block b, int replication) {
    BlockInfo info = map.get(b);
    if (info == null) {
      info = new BlockInfo(b, replication);
      map.put(info, info);
    }
    return info;
  }

  检查map是否存在该BlockInfo,若没有则create一个BlockInfo,put 到map中。

    (2)

  BlockInfo addINode(Block b, INodeFile iNode) {
    BlockInfo info = checkBlockInfo(b, iNode.getReplication());
    info.inode = iNode;
    return info;
  }

  添加特定BlockInfo的INode对象。

    (3)

  void removeBlock(BlockInfo blockInfo) {
    if (blockInfo == null)
      return;
    blockInfo.inode = null;
    for(int idx = blockInfo.numNodes()-1; idx >= 0; idx--) {
      DatanodeDescriptor dn = blockInfo.getDatanode(idx);
      dn.removeBlock(blockInfo); // remove from the list and wipe the location
    }
    map.remove(blockInfo);  // remove block from the map
  }

  删除该BlockInfo对象。删除涉及到几个结构,首先是map中,然后是从DatanodeDescriptor中删除对应的Block。

posted on 2012-03-18 11:44  萌@宇  阅读(701)  评论(0编辑  收藏  举报

导航