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中获取文件数据。

相关推荐
xixixi777771 小时前
《从心理诱导突破Claude到AI仿冒直播首张拘留单:AI安全、监管与商用的三重转折点》
大数据·网络·人工智能·安全·ai·大模型·风险
立控信息LKONE1 小时前
门禁机、控制器等库室安防设施、实现库室智能联动,一体报警
大数据·人工智能·安全
小真zzz1 小时前
中立第三方:搜极星的突围之路
大数据·人工智能
yzx9910131 小时前
软件脚本定制开发:从需求到交付的技术实战指南
大数据·人工智能·数据挖掘
Yolo566Q1 小时前
环境土壤物理模型HYDRUS1D/2D/3D实践技术应用系统性学习
大数据·开发语言·gpt·学习·arcgis·r语言
T06205141 小时前
【数据集】上市公司企业业务招待费数据 (2012-2024年)
大数据
WL_Aurora2 小时前
MapReduce框架原理深度解析 | Shuffle机制、切片分区、Join全攻略
大数据·hadoop·mapreduce
赵渝强老师2 小时前
【赵渝强老师】Hadoop的伪分布部署模式
大数据·hadoop·分布式
沐泽__2 小时前
Elasticsearch 磁盘水位线详解:从触发只读到安全解锁
大数据·安全·elasticsearch