HDFS(一)架构及文件读写流程

Hadoop 中有三大组件:HDFS、MapReduce、YARN,HDFS 负责大文件存储的问题,MapReduce 负责大数据计算,而 YARN 负责资源的调度,接下来的文章我会一一介绍这几个组件。今天我们先来聊聊 HDFS 的架构及文件的读写流程。

总体架构

HDFS 设计的目的是为了存储大数据集的文件,因此一台服务器是应付不了的,我们需要一个集群来实现这个目标。当用户需要存储一个文件时,HDFS 会将这个文件切分为一个个小的数据块(在 2.x 的版本中,每个数据块默认大小为 128M),再对每个数据块进行存储,当所有的数据块存储成功之后,才表示这个数据存到 HDFS 中了。HDFS 还会对每个数据块进行备份操作,使系统具有高容错性。

了解了 HDFS 的设计目标之后,我们来看下它的总体架构,下面这张图是从 HADOOP 官网扣下来的,除了刚刚提到的数据块(Blocks),还有两个比较重要的角色:NameNode 和 DataNode。DataNode 即数据节点,顾名思义,它们是存储真实数据的节点(每个节点就是一台服务器)。而 NameNode 呢?它主要维护元数据信息,包括:

  • 整个系统的文件和目录以及它们的层级关系
  • 文件目录的所有者及其权限
  • 每个文件由哪些数据块组成和每个数据块的名称

但是这里需要注意的是,NameNode 不会将每个数据块的地址信息持久化到磁盘中,这些信息会在 NameNode 启动之后从各个 DataNode 中获取并存放在内存中,因为从内存中读取数据比从磁盘中读取数据快得多,这无疑大大提高了客户端读取文件的性能。

以下部分参考:https://www.cnblogs.com/smartloli/p/4342340.html

不过,这张图并没有把 HDFS 中另一个重要的角色标出来 --- Secondary NameNode,这个家伙又是干什么的呢?这就不得不提到 HDFS 文件写入过程中涉及到的两个文件 --- fsimage 和 edits。fsimage 是 NameNode 启动时对整个文件系统的快照,edits 是在 NameNode 启动后,对整个系统的改动序列,在系统重启时,会将 edits 合并到 fsimage 文件上。由于 NameNode 会长时间运行,写入的数据量大时,edits 文件会变得很大,这就会出现下面这些问题:

  • edits 文件会变得很大,如何去管理这个文件?
  • NameNode 的重启会花费很长的时间,因为有很多改动要合并到 fsimage 文件上
  • 如果 NameNode 宕掉了,那我们就丢失了很多改动,因此此时的 fsimage 文件时间戳比较旧(也有观点认为丢失的改动不是特别多,因此丢失的只是那些在内存中,没有写入到 edits 文件中的改动)。

为了解决上述问题,就出现了 Secondary NameNode。它会定时到 NameNode 中获取 edits 文件,并更新到 fsimage 上,一旦有新的 fsimage 文件,它就将其拷贝会 NameNode 上。NameNode 下次启动时直接使用这个 fsimage,省去了合并 fsimage 和 edits 文件的过程。这就是 Secondary NameNode 在 HDFS 中的作用。

读写流程分析

接下来的读写流程我们会结合代码进行分析,使用 JAVA API 对 HDFS 进行操作非常简单,利用 maven 环境,在 pom.xml 中加入 hdaoop client 的依赖就可以使用 HDFS 的 API 了。

<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-client</artifactId>
    <version>#{hadoop.version}</version>
</dependency>

读数据流程

HDFS 文件读取的的代码如下:

public static void main(String[] args) throws Exception{
    Configuration conf = new Configuration();
    /*
     * hadoop 可以跟多种文件系统交互,根据下图,我们也可以看到 FileSystem 有多种实现
     * 为了让 hadoop 知道是与什么文件系统进行交互的,我们需要在配置文件中指定。
     */
    conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");

    String uri = "hdfs://hadoop-master:9000/e.txt";
    // 获取文件系统,这里 FileSystem 具体实现为上面指定的 DistributedFileSystem
    FileSystem fs = FileSystem.get(URI.create(uri), conf);

    OutputStream out ;
    FSDataInputStream in = null;
    try {
        out = new FileOutputStream("e.txt");
        in = fs.open(new Path(uri));

        // 读取文件到本地
        byte[] buf = new byte[4096];
        for(int bytesRead = in.read(buf); bytesRead >= 0; bytesRead = in.read(buf)) {
            out.write(buf, 0, bytesRead);
        }
    } finally {
        IOUtils.closeStream(in);
    }
}

根据上述代码,我们也大致可以猜出 HDFS 读取文件的流程了:

  1. 获取交互的文件系统(FileSystem),交互的文件系统需要我们在配置文件中指定。FileSystem 的 HDFS 实现类是 DistributedFileSystem(步骤一)。
  2. DistributedFileSystem 通过远程过程调用(RPC)来调用 namenode,nanenode 将包含文件数据块的 datanode 返回给客户端,并根据 datanode 与客户端的距离来排序(步骤二)。
  3. DistributedFileSystem 返回 FSDataInputStream 对象,用来读取数据。客户端通过调用 read 方法,从最近的一个 datanode 读取每个数据块的数据,当读取完一个数据块之后,接着查找包含该数据块且离得最近的 datanode 进行读取,直到读取完最后一个数据块,这些对用户来说都是透明的。(步骤三、步骤四)
  4. 当整个文件读取完毕之后,调用 close 方法,关闭与 nanode 和 datanode 的连接。

写数据流程

public static void main(String[] args) throws IOException {
    Configuration conf = new Configuration();
    conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");

    String uri = "hdfs://192.168.1.150:9000/friend/test.txt";
    FileSystem fs = FileSystem.get(URI.create(uri), conf);

    InputStream in = null;
    FSDataOutputStream out = null;
    try {
        in = new FileInputStream("e-friend.txt") ;
        out = fs.create(new Path(uri));
        byte[] buf = new byte[4096];

        for(int bytesRead = in.read(buf); bytesRead >= 0; bytesRead = in.read(buf)) {
            out.write(buf, 0, bytesRead);
        }
    }  finally {
        if (in != null)
            in.close();
        if (out != null)
            out.close();
    }
}

读写数据的代码相似,但是写数据的过程更加复杂,我们一步一步来看。

  1. 第一步还是一样的,初始化 FileSystem(步骤一),之后 FileSystem 调用 create 方法来创建文件,此时通过远程过程调用 namenode,namenode 会检查以确保这个文件不存在以及客户端有新建该文件的权限,如果检查通过 namenode 会在 edits 记录该操作(步骤二)。
  2. FileSystem 返回 DFSoutputStream 对象,该对象负责处理 datanode 和 namenode 的通信。当客户端写入数据时(步骤三),DFSOutputStream 将它分为一个个数据包,存到内部的一个队列中(数据队列),DFSOutputStream 处理每个数据块时,先挑选出适合存储该数据块的一组 datanode,这一组 datanode 构成一个管道,假设 HDFS 副本数为 3,那么 DFSOutputStream 将该数据块发送带管道中的第一个 datanode,该 datanode 存储该数据块并把它发送到第二个 datanode 中,以此类推(步骤四)。
  3. 除了数据队列,DFSOutputStream 还存储了一个确认队列,收到管道中所有 datanode 的确认信息之后,该数据包才会从确认队列中删除(步骤五)。
  4. 客户端写入后,对数据流(DFSOutputStream)调用 close 方法(步骤六)。
  5. 告知 namenode 文件写入完成(步骤七)。

原文地址:https://www.cnblogs.com/firepation/p/11405056.html

时间: 2024-08-27 08:35:53

HDFS(一)架构及文件读写流程的相关文章

HDFS文件读写流程

1.HDFS文件读取流程: 2.HDFS写入文件流程

HDFS文件读写流程简单图解

在活动反思文件系统中

Linux文件读写机制及优化方式

导读 Linux是一个可控性强的,安全高效的操作系统.本文只讨论Linux下文件的读写机制,不涉及不同读取方式如read,fread,cin等的对比,这些读取方式本质上都是调用系统api read,只是做了不同封装.以下所有测试均使用open, read, write这一套系统api. 缓存 缓存是用来减少高速设备访问低速设备所需平均时间的组件,文件读写涉及到计算机内存和磁盘,内存操作速度远远大于磁盘,如果每次调用read,write都去直接操作磁盘,一方面速度会被限制,一方面也会降低磁盘使用寿

从内核文件系统看文件读写过程

系统调用 操作系统的主要功能是为管理硬件资源和为应用程序开发人员提供良好的环境,但是计算机系统的各种硬件资源是有限的,因此为了保证每一个进程都能安全的执行.处理器设有两种模式:“用户模式”与“内核模式”.一些容易发生安全问题的操作都被限制在只有内核模式下才可以执行,例如I/O操作,修改基址寄存器内容等.而连接用户模式和内核模式的接口称之为系统调用. 应用程序代码运行在用户模式下,当应用程序需要实现内核模式下的指令时,先向操作系统发送调用请求.操作系统收到请求后,执行系统调用接口,使处理器进入内核

文件读写原理(转)

系统调用 操作系统的主要功能是为管理硬件资源和为应用程序开发人员提供良好的环境,但是计算机系统的各种硬件资源是有限的,因此为了保证每一个进程都能安全的执行.处理器设有两种模式:"用户模式"与"内核模式".一些容易发生安全问题的操作都被限制在只有内核模式下才可以执行,例如I/O操作,修改基址寄存器内容等.而连接用户模式和内核模式的接口称之为系统调用. 应用程序代码运行在用户模式下,当应用程序需要实现内核模式下的指令时,先向操作系统发送调用请求.操作系统收到请求后,执行

hadoop学习笔记(六):HDFS文件的读写流程

一.HDFS读取文件流程: 详解读取流程: Client调用FileSystem.open()方法: 1 FileSystem通过RPC与NN通信,NN返回该文件的部分或全部block列表(含有block拷贝的DN地址). 2 选取举栗客户端最近的DN建立连接,读取block,返回FSDataInputStream. Client调用输入流的read()方法: 1 当读到block结尾时,FSDataInputStream关闭与当前DN的连接,并未读取下一个block寻找最近DN. 2 读取完一

大数据【二】HDFS部署及文件读写(包含eclipse hadoop配置)

一 原理阐述 1' DFS 分布式文件系统(即DFS,Distributed File System),指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网络与节点相连.该系统架构于网络之上,势必会引入网络编程的复杂性,因此分布式文件系统比普通磁盘文件系统更为复杂. 2' HDFS 借此,关于GFS和HDFS的区别与联系查看 我于博客园找到的前辈的博客>>http://www.cnblogs.com/liango/p/7136448.html HDFS(Hadoop Dis

大数据系列文章-Hadoop的HDFS读写流程(二)

在介绍HDFS读写流程时,先介绍下Block副本放置策略. Block副本放置策略 第一个副本:放置在上传文件的DataNode:如果是集群外提交,则随机挑选一台磁盘不太满,CPU不太忙的节点. 第二个副本:放置在与第一个副本不同的机架的节点上. 第三个副本:与第二个副本相同机架的节点. 更多副本:随机节点. HDFS写流程 客户端发请求给NameNode,我想保存一个文件A,这时候在NameNode会有一个标识,标识为A_copy(文件不可用). 根据副本放置策略,返回三个副本的可放置位置列表

HDFS API 文件读写代码演示

一:准备工作 1.新建class类 2.开启HDFS服务 3.将配置文件拷贝进resources路径 方便了Configuration的读取配置. 二:读出HDFS文件系统中的文件到控制台 4.读出在路径中的文件,显示在控制台上 5.分别解析,获取文件系统(两种方式) (方式一) (方式二) 这种方式不需要复制配置文件进resources,但是这种被写死了. 6.分别解析,写入流 7.优化readFile 三:把文件上传到HDFS上