HDFS源码(二)

DataNode启动源码

创建HttpServer

初始化DataNode Rpc服务

获取NameNode Rpc代理

Datanode向NameNode注册

DataNode与NameNode周期心跳及block块汇报

数据上传源码

创建文件系统及初始化DFSClient

连接NN创建目录

启动DataStreamer线程

向dataQueue队列中写入packet

设置副本写入策略源码

java 复制代码
protected Node chooseTargetInOrder(int numOfReplicas, 
                               Node writer,
                               final Set<Node> excludedNodes,
                               final long blocksize,
                               final int maxNodesPerRack,
                               final List<DatanodeStorageInfo> results,
                               final boolean avoidStaleNodes,
                               final boolean newBlock,
                               EnumMap<StorageType, Integer> storageTypes)
                               throws NotEnoughReplicasException {
  // 计算结果列表的大小,默认初始 results 为0,result集合表示副本所在的节点
  final int numOfResults = results.size();
  // 如果结果列表为空
  if (numOfResults == 0) {
    // 选择本地节点作为第一个副本存储位置,并向result中加入节点
    DatanodeStorageInfo storageInfo = chooseLocalStorage(writer,
        excludedNodes, blocksize, maxNodesPerRack, results, avoidStaleNodes,
        storageTypes, true);

    //writer第一个副本要写出的DataNode节点
    writer = (storageInfo != null) ? storageInfo.getDatanodeDescriptor()
                                   : null;

    //减去一个副本后,如果为0则返回,writer,否则不返回,继续
    if (--numOfReplicas == 0) {
      return writer;
    }
  }
  //第一个副本所在DN节点
  final DatanodeDescriptor dn0 = results.get(0).getDatanodeDescriptor();

  if (numOfResults <= 1) {
    //选择远程机架存放第二个副本
    chooseRemoteRack(1, dn0, excludedNodes, blocksize, maxNodesPerRack,
        results, avoidStaleNodes, storageTypes);
    if (--numOfReplicas == 0) {
      //writer第一个副本要写出的DataNode节点
      return writer;
    }
  }

  if (numOfResults <= 2) {
    //第二个副本所在DN节点
    final DatanodeDescriptor dn1 = results.get(1).getDatanodeDescriptor();
    if (clusterMap.isOnSameRack(dn0, dn1)) {//如果dn0与dn1是同一机架,第三个副本选择不同机架
      chooseRemoteRack(1, dn0, excludedNodes, blocksize, maxNodesPerRack,
          results, avoidStaleNodes, storageTypes);
    } else if (newBlock){//如果是新块,选择与dn1 第二个副本所在节点相同的机架上放第三个副本
      chooseLocalRack(dn1, excludedNodes, blocksize, maxNodesPerRack,
          results, avoidStaleNodes, storageTypes);
    } else {//随机选择一台节点存储第3个副本
      chooseLocalRack(writer, excludedNodes, blocksize, maxNodesPerRack,
          results, avoidStaleNodes, storageTypes);
    }
    if (--numOfReplicas == 0) {
      //writer第一个副本要写出的DataNode节点
      return writer;
    }
  }
  //大于3个副本,随机选择节点存放副本
  chooseRandom(numOfReplicas, NodeBase.ROOT, excludedNodes, blocksize,
      maxNodesPerRack, results, avoidStaleNodes, storageTypes);
  //writer第一个副本要写出的DataNode节点
  return writer;
}

"chooseTargetInOrder"方法代码逻辑为block 副本找到存储节点的策略,然后返回block所在的第一个节点,首先第一个block存储在本机,第二个block存储在远程机架,第三个副本存储时先判断是否第一个副本和第二个副本是否在同一机架,如果在同一机架,那么第三个副本选择不同机架进行存储,否则选择与第二个副本相同机架的随机节点进行存储。最终该方法返回存储第一个副本的DataNode节点。

客户端与DataNode建立socket通信

向Datanode中写入数据

数据读取源码

数据 从HDFS中读取数据代码如下:

java 复制代码
public class ReadDataFromHDFS {
    public static void main(String[] args) throws IOException, InterruptedException {
        Configuration conf = new Configuration();

        //创建FileSystem对象
        FileSystem fs = FileSystem.get(URI.create("hdfs://node1:8020/"),conf,"root");

        //创建HDFS文件路径
        Path path = new Path("/test.txt");
        FSDataInputStream in = fs.open(path);


        //读取HDFS中数据
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        String newLine = "";
        while((newLine = br.readLine()) != null) {
            System.out.println(newLine);
        }

        //关闭流对象
        br.close();
        in.close();
    }
}

HDFS中数据读取源码相对简单,客户端从HDFS中获取文件数据时,首先会向NameNode获取文件相关的block信息,然后连接各个Datanode以流方式读取数据即可。

连接NameNode获取block信息

"namenode.getBlockLocations(src, start, length)"最终调用到NameNodeRpcServer.getBlockLocations(...)方法。

回到DFSClient.open()方法中,最终通过执行"return openInternal(locatedBlocks, src, verifyChecksum);"返回DFSInputStream对象。

客户端通过socket连接DataNode

DataNode返回block数据流

最终通过readBuffer(...)从DataNode中获取文件数据。

相关推荐
jkyy20145 小时前
深耕AI健康医疗数据智库,赋能企业构建主动健康管理新生态
大数据·人工智能·健康医疗
2601_961946087 小时前
AI API 网关实战:从单 Key 管理到企业级多租户架构
大数据·人工智能·金融·架构·api·个人开发
大大大大晴天9 小时前
Flink CDC 深度解析:从原理到实践的全链路指南
大数据·flink
IT新视界10 小时前
Elasticsearch信创国产化替代
大数据·elasticsearch·搜索引擎
汇策研习社10 小时前
改良版ADX指标实战指南:告别传统ADX滞后、震荡误判难题
大数据·经验分享·金融·区块链·fastbull
SelectDB10 小时前
宽表元数据膨胀怎么解?Doris Segment V3 对比 Parquet、Lance
大数据·数据库·数据分析
隔窗听雨眠11 小时前
从追赶者到定义者:中国BI如何借助AI实现弯道超车
大数据·人工智能
cspttty11 小时前
二本软件工程专业好就业吗?毕业后能做哪些岗位
大数据·软件工程
智圣新创0111 小时前
高校全域治理决策效能升级 智圣新创决策中台落地实操与行业趋势研判
大数据·人工智能·物联网
2401_8595062412 小时前
玉石加工全链路技术变革:五大维度拆解材质改性、精密雕刻与智能溯源
大数据·人工智能