Namenode计算client与datanode距离方法pseudoSortByDistance分析

 在Hadoop读数据的过程中,会从与Client端最这距离的datanode的block副本去读数据,那这个距离怎么计算?策略是与Client同一个datanode结点的优先权最高,其次是本机架结点,否则随机。我们知道在读数据的时候Client首先会与namenode打交道,向namenode发送RPC请求获取block及对应的datanode位置列表,由Namenode端计算距离后按距离由近及远,返回位置列表。

 

NameNode类

 

  public LocatedBlocks   getBlockLocations(String src,
                                          long offset,
                                          long length) throws IOException {
    myMetrics.numGetBlockLocations.inc();
    return namesystem.getBlockLocations(getClientMachine(),
                                        src, offset, length);
  }

 

FSNamesystem类

  /**
   * Get block locations within the specified range.
   *
   * @see #getBlockLocations(String, long, long)
   */
  LocatedBlocks getBlockLocations(String clientMachine, String src,
      long offset, long length) throws IOException {
    if (isPermissionEnabled) {
      checkPathAccess(src, FsAction.READ);
    }

    LocatedBlocks blocks = getBlockLocations(src, offset, length, true);
    if (blocks != null) {
      //sort the blocks
      DatanodeDescriptor client = host2DataNodeMap.getDatanodeByHost(
          clientMachine);
      for (LocatedBlock b : blocks.getLocatedBlocks()) {
        clusterMap.pseudoSortByDistance(client, b.getLocations());     //调用的是NetworkTopology类的pseudoSortByDistance方法计算client与datanode的距离方法
      }
    }
    return blocks;
  }

 

 NetworkTopology类

 

计算距离的核心部分


  public void pseudoSortByDistance( Node reader, Node[] nodes ) {
    int tempIndex = 0;
    if (reader != null ) {
      int localRackNode = -1;
      //scan the array to find the local node & local rack node
      for(int i=0; i<nodes.length; i++) {        //分别通过tempIndex和localRackNode标识是否找到本地结点和本机架结点,两类都找到则退出循环
        if(tempIndex == 0 && reader == nodes[i]) { //local node  //发现本地结点
          //swap the local node and the node at position 0
          if( i != 0 ) {
            swap(nodes, tempIndex, i); //找到本地结点并且不在列表的第一个位置,与第一个位置交换
          }
          tempIndex=1;
          if(localRackNode != -1 ) {  //在找到本地的时候如果发生已经有了本架,并且本架在第一个位置,将本架的标量指定到本地的位置(因为前面已经把本地的与第一个位置交换了)
            if(localRackNode == 0) {
              localRackNode = i;
            }
            break;
          }
         
        }
        else if(localRackNode == -1 && isOnSameRack(reader, nodes[i])) { //发现本机架结点
          //local rack
          localRackNode = i;
          if(tempIndex != 0 ) break;
        }
      }

      // swap the local rack node and the node at position tempIndex,
      //把本架结点放第一个位,或第二位,如果有本架结点,跟tempIndex交换,tempIndex要么为0,要么为1,分别交换没本地结点,有本地结点的情况
      //没有本地,本架则放第一位,有本地,本架放第二位,swap tempIndex就做到了
      if(localRackNode != -1 && localRackNode != tempIndex ) {
        swap(nodes, tempIndex, localRackNode);
        tempIndex++;
      }
    }
   
    // put a random node at position 0 if it is not a local/local-rack node
    //随机取结点放置在第一个位置,此语句没有本地和本架才发生,感觉这个没有多少意义
    if(tempIndex == 0 && nodes.length != 0) {
      swap(nodes, 0, r.nextInt(nodes.length));
    }
  }
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值