【Hadoop---07】HDFS 读 / 写 数据流程(面试重点)

文章目录

  • 1. HDFS写数据
    • 1.1 HDFS写数据流程
    • 1.2 关于副本结点的选择流程
  • 2. HDFS读数据

1. HDFS写数据

1.1 HDFS写数据流程

【Hadoop---07】HDFS 读 / 写 数据流程(面试重点)_第1张图片
HDFS读写流程:

  1. HDFS客户端创建 DistributedFileSystem(分布式文件系统)类的对象实例。【该对象中封装了与HDFS文件系统操作的相关方法】
  2. 调用DistributedFileSystem对象create()方法,通过 RPC 请求 NameNode 创建文件。
    NameNode执行各种检查判断: 目标文件是否存在、父目录是否存在、客户端是否具有创建文件的权限。
    检查通过后返回 FSDataOutputStream 输出流对象给客户端用于写数据
  3. 客户端通过 FSDataOutputStream 输出流开始写入数据
    ① NameNode根据网络拓扑挑选出一组DataNode用于存放数据,默认是3副本存储。
    ② DataStreamer将数据包流式传输到管道(pipeline)的第一个 DataNode,该DataNode存储数据包并将它发送到 pipeline 的第二个DataNode。同样的,第二个DataNode存储数据包并发送给第三个(也是最后一个)DataNode】
  4. 传输的反方向上,会通过ACK校验数据包传输是否成功
  5. 客户端完成数据写入后,在 FSDataOutputStream 输出流上调用 close() 方法关闭
  6. 客户端DsitributedFileSystem 告知NameNode文件写入完成,等待NameNode确认。
    【因为NameNode已经知道文件由哪些块组成,因此仅需等待最小复制块即可成功返回。最小复制是由参数 dfs.namenode.replication.min 指定,默认是1。即只要有1个副本上传成功,NameNode就认为已经上传成功,如果其他DataNode有缺失的块,可以通过这个DataNode继续复制】

抓住几个点:

  1. NameNode收到请求后并不是立即响应,而是要检查:目标文件是否存在、父目录是否存在、客户端是否具有创建文件的权限。
  2. 进行分布式数据传输时,并不是并行的传输,而是串行并发的传输。
    因为这样可以将客户端压力转到服务器端来,给用户更好的体验。
    【Hadoop---07】HDFS 读 / 写 数据流程(面试重点)_第2张图片
  3. ① 客户端要向DataNode写数据时,是以一种管道(pipeline)的方式。将文件块拆分成多个64KB的数据包(packet),多个数据包流水式并发的对同一个DataNode进行写入。
    ② 传输单元为64KB,每个单元由若干个分组组成,每个分组为512B的数据 + 4B的校验位 = 516B

1.2 关于副本结点的选择流程

问:在前面说到写数据时,NameNode根据网络拓扑挑选出一组DataNode用于存放数据。那么NameNode是怎么挑选DataNode的?

【Hadoop---07】HDFS 读 / 写 数据流程(面试重点)_第3张图片
答:假设副本数为3,则:

  1. 第一个副本在Client所在结点上;若客户机在集群外,则在集群中随机选一个(因为此时所有DataNode结点与Client距离相等)【保证效率】

    节点距离的计算:两个节点到达最近的共同祖先的距离总和。

  2. 第二个副本在另一个机架上随机选一个结点。【保证可靠】

  3. 第三个副本在第二个副本所在机随机选一个。【保证效率】

2. HDFS读数据

【Hadoop---07】HDFS 读 / 写 数据流程(面试重点)_第4张图片

HDFS读数据的整体流程:

  1. HDFS客户端创建 DistributedFileSystem(分布式文件系统)类的对象实例。

  2. 调用DistributedFileSystem对象read()方法,通过 RPC 请求 NameNode 读取文件。
    NameNode执行各种检查判断: 目标文件是否存在、父目录是否存在、客户端是否具有读取文件的权限。
    检查通过后返回 FSDataInputStream 输出流对象给客户端用于读数据

  3. 客户端通过 FSDataInputStream 输出流开始写入数据
    ① 首先选择哪个DataNode结点?两个因素 {距离最近, DataNode所在服务器负载均衡低},然后从中读取第一个文件快blk_1
    ② 请求第二个文件块blk_2时,是在已经读取完成了blk_1之后才会发出该请求,是串行读,不是多线程并行。最后将读到的blk_2数据追加到blk_1末尾,就可以拼接成一个完整的文件。

    所以,我们在 hadoop 服务器上的data文件夹中找到hadoop存放数据的文件夹$HADOOP_HOME/data/dfs/data/current/BP-xxxxxxx/current/finalized/subdir0/subdir0,在里面将某个文件的几个blk_xxx按顺序拼接,也能恢复出原文件。

    # 将blk_1的数据写入abc.txt
    cat blk_1 >> abc.txt
    # 将blk_2的数据追加到abc.txt
    cat blk_2 >> abc.txt
    # 此时就可以恢复出文件abc.txt
    
  4. 客户端读完数据后,在 FSDataInputStream 输出流上调用 close() 方法关闭

  5. 客户端DsitributedFileSystem 告知NameNode文件读出完成。

你可能感兴趣的:(#,Hadoop,hadoop,hdfs,面试)