HDFS体系结构及常见功能

本文主要是介绍HDFS的体系结构和常用操作,涉及到的知识点如下:

  1. HDFS的体系结构
  2. 数据上传
  3. 数据下载

HDFS的体系结构

Hadoop的生态圈,包括HDFS、Yarn、HBase都是主从结构。对于HDFS来说,它的主节点是NameNode,从节点是DataNode,还有一个更新最新状态的SecondaryNameNode,下面我们对这几个结点做详细的解释。

  1. NameNode:名称节点

    (1)职责:

    • 管理、维护HDFS;
    • 接收客户端的请求:上传、下载、创建目录等;
    • 维护两个非常重要的文件:edits文件 –> 记录了操作日志;fsimage文件 –> 记录HDFS元信息

    (2)HDFS操作日志:edits文件

    位置:find . -name edits* (在当前目录下查找以edits打头的文件)

    ​ 最新的操作日志以edits_inprogress***开头

    记录:Edits文件保存了自最后一次检查点之后所有针对HDFS文件系统的操作,比如:增加文件、重命名文件、删除目录等等

    都是二进制

    HDFS提供了一个工具:edits viewer 日志查看器,可以将操作日志转化为XML格式来查看。命令如下:

    hdfs oev 命令将日志(二进制)输出为XML文件 -i表示输入,-o表示输出
    hdfs oev -i edits_inprogress_0000000000000000208 -o ~/a.xml

    (3)HDFS的元信息:fsimage文件

    位置:和edits文件在一起

    记录:fsimage是HDFS文件系统存于硬盘中的元数据检查点,里面记录了自最后一次检查点之前HDFS文件系统中所有目录和文件的序列化信息(数据块的位置、冗余信息)

    也是二进制

    HDFS提供了一个工具:image viewer查看器,可以将操作日志转化为文本或者XML格式来查看

    hdfs oiv 命令将日志(二进制)输出为文本文件 -i表示输入,-o表示输出
    hdfs oiv -i fsimage_0000000000000000207 -o ~/b.txt (文本)
    hdfs oiv -i fsimage_0000000000000000207 -o ~/c.xml -p XML(xml文件)
  2. DataNode:数据结点

    数据块大小:

    • 1.x版本 64M
    • 2.x笨笨 128M

    位置:find . -name blk*(blk是block的简写)

    一般原则:数据块的冗余度一般跟数据结点个数一致,最大不要超过3。在生产环境下,至少2个数据结点

    blk_*表示数据块

    blk_*.meta表示数据块的元信息

  3. SecondaryNameNode:第二名称结点

    作用:把edits中最新的状态信息合并到fsimage文件中,即日志合并。合并原理图如下。

    HDFS体系结构及常见功能_第1张图片

    NameNode和SecondaryNameNode在一起的原因是为了效率问题,因为两者在一起,SecondaryNameNode在合并最新的edits到fsimage中时,只需要执行cp操作即可;在合并后,把最新的fsimage上传回NameNode下的fsimage

    什么时候合并?当HDFS发出检查点(checkpoint)的时候。默认会在两种情况下发出检查点:

    ​ (1)每隔60分钟。可通过修改参数,改变时间

    ​ (2)当edits文件达到64M。可通过修改参数,改变阈值

    补充:Oracle数据库中也有检查点,如果发生检查点,会以最高优先级唤醒数据库写进程(DBWn)把内存中的脏数据写到数据文件上(持久化)

    注意:NameNode和SecondaryNameNode名字看起来差不多,但是两者并没有什么关系

  4. HDFS存在的问题:

    (1)NameNode单点故障,即一旦出现问题整个系统就瘫痪

    ​ 解决方案:Hadoop1.0中,没有解决方案。

    ​ Hadoop2.0中,使用Zooker实现Name的HA(高可用性,后面会讲到)功能。

    (2)NameNode压力过大,且内存受限,影响系统扩展

    ​ 解决方案:Hadoop1.0中,没有解决方案

    ​ Hadoop2.0中,使用NameNode的联盟实现其水平扩展

HDFS上传

先来一张HDFS文件上传的流程图:

HDFS体系结构及常见功能_第2张图片

看完流程图就是具体的上传了,有两种方式:

(1)命令行:

-put                上传数据  hdfs dfs -put data.txt /input
-copyFromLocal      上传数据  hdfs dfs -copyFromLocal data.txt /input
-moveFromLocal      上传数据(相当于 ctrl+x 剪切)

(2)JavaApi:以下是通过javaApi进行文件上传的代码块,以Window下的FinancialWorkStationEdu.exe文件为例(141M):

//使用自己写流的方式来实现
@Test
    public void testUpload1() throws Exception {
         //设置当前用户为root用户(不设置可能出现权限异常)
        //System.setProperty("HADOOP_USER_NAME","root");

        //构造一个输入流
        FileInputStream in = new FileInputStream("D:\\download\\chromeDownload\\FinancialWorkStationEdu.exe");

        //配置NameNode地址(在上一边环境变量的配置时,我们配置过它的key和value,直接复制过来即可)
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS","hdfs://192.168.171.113:9000");

        //客户端
        FileSystem client = FileSystem.get(conf);

        //得到一个输出流
        FSDataOutputStream out = client.create(new Path("/input/a.exe"));

        //构造缓冲区
        byte[] buffer = new byte[1024];
        int len = 0;
        while((len = in.read(buffer)) > 0){
            //将读到的数据写入
            out.write(buffer,0,len);
        }

        out.flush();

        out.close();
        in.close();
    }

//使用Hadoop提供的工具类来实现
@Test
    public void testUpload2() throws Exception {
        //设置当前用户为root用户(不设置可能出现权限异常)
        //System.setProperty("HADOOP_USER_NAME","root");

        //构造一个输入流
        FileInputStream in = new FileInputStream("D:\\download\\chromeDownload\\FinancialWorkStationEdu.exe");

        //配置NameNode地址(在上一边环境变量的配置时,我们配置过它的key和value,直接复制过来即可)
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS","hdfs://192.168.171.113:9000");

        //客户端
        FileSystem client = FileSystem.get(conf);

        //得到一个输出流
        FSDataOutputStream out = client.create(new Path("/input/b.exe"));
        //使用Hadoop提供的工具类来实现
        IOUtils.copyBytes(in,out,1024);
    }

在运行上面的代码之前有两个问题要注意:

  1. 我们使用到的这些API有些是Hadoop提供的,我们需要到hadoop里面把这些jar包拷贝下来,放到项目的lib目录。我们先看下Hadoop的目录结构:

    HDFS体系结构及常见功能_第3张图片

    然后我们需要把common下的lib包和hdfs下的lib拷贝下来即可。

  2. 权限配置,如果没有配置权限的话,会抛出以下异常:

    Caused by: org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.security.AccessControlException): Permission denied: user=cpMark, access=WRITE, inode=”/user/cpMark/input/a.exe”:root:supergroup:drwxr-xr-x

    即当前用户没有w权限

    处理这个异常,有以下几种方式:

    (1)关闭HDFS的权限检查。这个在hdfs-site.xml中我们是配置过为false,不过被我们注释没有打开,如下:

    ![HDFS权限配置](https://img-blog.csdn.net/20180505160012706?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NwX01hcms=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
    

    这里我们打开就可以正常运行了。运行结果如下:

    HDFS文件上传结果

    (2)设置一个属性。把自己设置为root用户,具体方式为在我们的JavaApi前面设置用户名(上面代码注释打开即可):

     //设置当前用户为root用户
     System.setProperty("HADOOP_USER_NAME","root");

    (3) -D的使用,通过-D获取命令行上的参数。比如:-Dname=Tom -Dgender=Male,那么我们在程序中就可以取到name参数和gender参数,具体如下:

     String name = System.getProperty("name");
     String gender = System.getProperty("gender");
     System.out.println(name+"\t"+gender);

    具体操作如下,新建一个带有main入口函数的类,copy以上代码,然后使用javac编译,编译成功之后,使用java命令执行,java -Dname=Tom -Dgender=Male XXX(编译出来的class文件)即可

    (4)改变input目录的权限

     hdfs dfs -chmod 777 /input

    这样就可以执行了。

HDFS下载

下载的话,和上传一样,先来张流程图,然后是代码:

HDFS体系结构及常见功能_第4张图片

看完流程图就是具体的上传了,有两种方式:

(1)命令行:

-copyToLocal   下载数据
-get           下载数据

(2)JavaApi:以下是通过javaApi进行文件下载的代码块,以hdfs /input目录下的a.exe,为例:

@Test
    public void testDownload1() throws Exception {
        //设置当前用户为root用户
        System.setProperty("HADOOP_USER_NAME", "root");

        //配置NameNode地址(在上一边环境变量的配置时,我们配置过它的key和value,直接复制过来即可)
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://192.168.171.113:9000");

        //构造客户端
        FileSystem client = FileSystem.get(conf);

        //构造一个输入流
        FSDataInputStream in = client.open(new Path("/input/a.exe"));

        //构造一个输出流  ----> D:\temp\a.exe
        OutputStream out = new FileOutputStream("D:\\temp\\a.exe");

        //构造一个缓冲区
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = in.read(buffer)) > 0) {
            //读取到了数据
            out.write(buffer, 0, len);
        }

        out.flush();

        out.close();
        in.close();
    }

    @Test
    public void testDownload2() throws Exception {
        //设置当前用户为root用户
        System.setProperty("HADOOP_USER_NAME", "root");

        //配置NameNode地址(在上一边环境变量的配置时,我们配置过它的key和value,直接复制过来即可)
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://192.168.171.113:9000");

        //构造客户端
        FileSystem client = FileSystem.get(conf);

        //构造一个输入流
        FSDataInputStream in = client.open(new Path("/input/a.exe"));

        //构造一个输出流  ----> D:\temp\a.exe
        OutputStream out = new FileOutputStream("D:\\temp\\b.exe");

        //使用工具类简化程序
        IOUtils.copyBytes(in, out, 1024);
    }

以上就是HDFS常见功能的介绍,一些其它的API,比如创建目录、查看目录及文件信息、查找某个文件在HDFS集群的位置等,只是API不同而已,大家可以自己去熟悉。

下一篇我会介绍HDFS的高级功能:回收站、快照、配额等。

你可能感兴趣的:(大数据)