Hadoop从入门到入土(第二十天)

Hadoop-HDFS总结


目录

一、HDFS概述

二、HDFS的Shell相关操作(开发重点)

三、HDFS的客户端API(数据的上传和下载)

四、HDFS的读写流程(面试重点)

五、NN和2NN(了解)

六、Datanode工作机制(了解底层原理)

A、工作机制​

B、Fsimage和Edits解析

C、CheckPoint时间设置

D、掉线时参数设置


一、HDFS概述

  1. HDFS的产生背景和定义
    1. 随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切的需要一种系统来管理多台机器上的文件,这就是分布式文件管理系统。HDFS只是分布式文件管理系统的一种。
      1. HDFS定义:HDFS,它是一个文件系统,用于存储文件,通过目录树来定位文件;其次,他是分布式的,有很多服务器联合起来实现其功能,集群中的服务器有各自的角色。        HDFS的使用场景:适合一次写入,多次读出的场景。一个文件经过创建、写入和关闭之后就不需要改变。
  2. 优缺点:
    1. 优点:
      1. 高容错性:数据自动保存多个副本。它通过增加副本的形式,提高容错性。某一个副本丢失后,它可以自动恢复。
      2. 适合处理大数据:数据规模:能够处理数据规模达到GB、TB、甚至PB级别的数据;文件规模:能过处理百万规模以上的文件数量,数量相当之大。
      3. 可构建在廉价的机器上,能过多副本机制就,提高可靠性。
    2. HDFS缺点
      1. 不适合低延时数据访问,比如毫秒级的存储及数据,是做不到的。
      2. 无法高效的对大量小文件进行存储。:存储大量小文件的话,它会占用NameNode大量的内存来存储文件目录和快信息。这样是不可取的,因为NameNode的内存总是有限的;小文件存储的寻址时间会超过读取时间,它违反了HDFS的设计目标。
      3. 不支持并发写入,文件随机修改:一个文件只能有一个写,不允许多个线程同时写;仅支持append(追加),不支持文件的随机修改。
  3. 组成
    1. NemeNode(nn):就是Matser,它是一个主管、管理者
    2. DataNode:就是Slave。NameNode下达命令DataNode执行实际的操作。
    3. Client:就是客户端
    4. SecondaryNameNode:并非NameNode的热备。党NameNode挂掉的时候,它并不能马上替换NamNode并提供服务。
  4. 文件块的大小
    1. HDFS中的文件在物理上分块存储(Block),块的大小可以通过参数配置来规定的,默认在Hadoop2x/3x版本中是128M,1x版本中是64M
    2. 寻址时间为传输时间的1%时,则为最佳状态。因此,传输时间=10ms/0.01=1000ms
    3. 总结:HDFS块的大小取决于磁盘的传输速率。

二、HDFS的Shell相关操作(开发重点)

  1. 基本语法:hadoop fs 具体命令 或者 hdfs dfs 具体命令(两个完全相同)
  2. 基本命令:准备工作:必须启动集群(sbin/start-dfs.sh和sbin/start-yarn.sh)
    1. hadooop fs -help 命令 输出这个命令的参数
    2. hadoop fs -mkdir 文件夹名称  创建文件夹
    3. (上传)hadoop fs -moveFromLocal 源路径 上传的路径 上传文件夹到hdfs,剪切的方式。
    4. (上传)hadoop fs -copyFromLocal 源路径 上传的路径  上传文件到hdfs,复制的方式。
    5. (追加)hadoop fs -appendToFile 要追加的文件路径 被追加的文件路径 在一个文件里的内容后追加新的内同。
    6. (下载)hadoop fs -get 源文件的路径  目标路径  从hdfs下载
  3. HDFS直接操作
    1. (-ls)hadoop fs -ls 文件夹路径 显示目录信息
    2. (-cat) hadoop fs -cat 文件的路径   查看文件内容
    3. (-chgrp、chmod、chown)hadoop fs -chmod 666 修改文件权限  hadoop fs -chown nancheng:nancheng 文件路径  修改所属用户
    4. (makdir)hadoop fs -makdir 新的文件夹路径 创建目录
    5.  (-cp)hadoop fs -cp 原始路径 目标路径 从HDFS的一个路径拷贝到另一个路径
    6. (-mv)hadoop fs -mv 源文件路径 目标路径 移动文件
    7. (-tail) hadoop fs  -tail 源文件路径  显示一个文件末尾1kb的数据
    8. (-rm)hadoop fs -rm 源文件路径 删除文件夹或文件
    9. (-rm -r)hadoop fs -rm -r 源文件路径 递归删除文件夹
    10. (-du)hadoop fs -du -s -h 源文件路径 统计文件夹的大小信息
    11. (-setrep)hadoop fs -setrep 源文件夹路径 更改副本数量

三、HDFS的客户端API(数据的上传和下载)

  1. 配置Hadoop环境变量
  2. 配置maven环境
  3. 在软件商店下载idea(在插件里搜索中文可以下载中文插件)
  4. 打开idea-》新建-》点maven-》下一步->点开下拉箭头
  5.  修改maven路径->文件->设置->
  6.  添加依赖
    <dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>3.1.3</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.30</version>
        </dependency>
    </dependencies>
    

  7. 在项目的src/main/resources目录下,新建一个文件,命名为“log4j.properties”,在文件中填入

    log4j.rootLogger=INFO, stdout  
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender  
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout  
    log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n  
    log4j.appender.logfile=org.apache.log4j.FileAppender  
    log4j.appender.logfile.File=target/spring.log  
    log4j.appender.logfile.layout=org.apache.log4j.PatternLayout  
    log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n

  8. 在java包下创建包名:hads(前置准备工作已经准备好了)

  9. 在hdfs包下创建一个类:HdfsClient  实现文件的上传、下载、更名、删除……

    @Before
        //因为一般前面和最后的步骤一样,可以封装起来
        public void init() throws URISyntaxException, IOException, InterruptedException {
            //连接的集群地址
            URI uri = new URI("hdfs://hadoop102:8020");
            //创建一个配置文件
            Configuration configuration = new Configuration();
            //修改对应的副本数
            configuration.set("dfs.replication", "2");
            //不是对应的用户会报权限不够的错误
            String user = "nancheng";
            //1.获取到客户端对象
            fs = FileSystem.get(uri, configuration, user);
        }
    
        @After
        public void close() throws IOException {
            //3.关闭资源
            fs.close();
        }
    
        /*
        创建目录
         */
        @Test
        public void testmkdir() throws URISyntaxException, IOException, InterruptedException {
    
            //2.创建一个文件夹
            fs.mkdirs(new Path("/xiyou1"));
        }
    
        /*
        上传
         */
        @Test
        public void testPut() throws IOException {
            //参数解读:参数1:表示是否删除原数据;参数2:是否允许覆盖;参数3:原数据路径;参数4:目的地路径
            fs.copyFromLocalFile(false, true, new Path("D:\\Hadoopruanjian\\lanxi\\新建文本文档.txt"), new Path("hdfs://hadoop102/lianxi"));
        }
    
        //文件的下载
        @Test
        public void testGet() throws IOException {
            //参数的解读,参数1,源文件是否删除;参数二,源文件的路径;参数三,目标地址的路径;参数四
            //fs.copyToLocalFile(false, new Path("hdfs://hadoop102/xiyou/huaguoshan1/sunwukong.txt"), new Path("D:\\Hadoopruanjian\\lanxi\\下载\\"), true);
            fs.copyToLocalFile(false, new Path("hdfs://hadoop102/lianxi"), new Path("D:\\Hadoopruanjian\\lanxi\\下载\\"), false);
        }
    
        //文件的删除
        @Test
        public void testRe() throws IOException {
            //参数解读:参数一,要删除的路径,参数二,是否递归删除
            //删除文件
            //fs.delete(new Path("/xiyou/huaguoshan1/sunwukong.txt"),false);
            //删除空目录
            // fs.delete(new Path("/xiyou1"),false);
            //删除非空目录
            fs.delete(new Path("/xiyou1"), true);
        }
    
        //文件的更名与移动
        @Test
        public void testmv() throws IOException {
            //参数解读:参数一,源文件路径;参数二,目标文件路径
    //        fs.rename(new Path("/xiyou/huaguoshan1/suwukong.txt"),new Path("/xiyou/huaguoshan1/sunwukong.txt"));
            //文件的移动和更名
    //        fs.rename(new Path("/xiyou/huaguoshan1/sunwukong.txt"),new Path("/qitiandashen.txt"));
            //文件目录的更名
            fs.rename(new Path("/xiyou"), new Path("/wukongjia"));
        }
    
        //获取文件详情
        @Test
        public void fileDetall() throws IOException {
            //获取文件信息
            RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);
            //遍历文件
            while (listFiles.hasNext()) {
                LocatedFileStatus fileStatus = listFiles.next();
    
                System.out.println("**************" + fileStatus.getPath() + "**************");
                System.out.println(fileStatus.getPermission());
                System.out.println(fileStatus.getOwner());
                System.out.println(fileStatus.getGroup());
                System.out.println(fileStatus.getLen());
                System.out.println(fileStatus.getModificationTime());
                System.out.println(fileStatus.getReplication());
                System.out.println(fileStatus.getBlockSize());
                System.out.println(fileStatus.getPath().getName());
    
                //获取块信息
                BlockLocation[] blockLocations = fileStatus.getBlockLocations();
                System.out.println(Arrays.toString(blockLocations));
    
    
    
            }
        }
        //判断是文件夹是文件
        @Test
        public void testFile() throws IOException {
            FileStatus[] listStatus = fs.listStatus(new Path("/"));
    
            for (FileStatus status : listStatus) {
                if (status.isFile()) {
                    System.out.println("文件:"+status.getPath().getName());
                }else {
                    System.out.println("目录:"+status.getPath().getName());
                }
    
            }
        }

四、HDFS的读写流程(面试重点)

HDFS文件写入流程:

  1. 客户端向Namenode发起文件写入的请求
  2. Namennode根据文件大小和文件块配置情况,返回给客户端所管理部分Datanode的信息;
  3. 客户端将文件划分成为多个块,根据Datanode的地址信息,按顺序写入到每一个Datanode块中

(图片来自尚硅谷) 、

网络拓扑-节点距离:两个节点到达最近的共同祖先的距离总和。

机架感知(副本存储节点选择)

  1. 第一个副本在客户端所在处的节点上选择一个,如歌客户端在集群外,随机选 一个
  2. 第二个副本在另一个机架的随机一个节点
  3. 第三个副本在第二个副本所在的机架的随机节点

HDFS读数据流程:

  1. 客户端向Namenode发起文件读取的请求
  2. Namenode返回文件存储的Damenode的信息
  3. 客户端读取文件信息

HDFS读数据流程

 (图片来自尚硅谷) 

五、NN和2NN(了解)

数据存储在内存:好处:计算快  坏处:可靠性差        磁盘:好处:可靠性高  坏处:计算慢 内存+磁盘->效率底   fslmage 存储数据(如果是随机读写效率a=10 a+10->a=20)        Edits 追加->

Namenode:HDFS的守护进程,用来管理文件系统的命名空间,负责记录文件是如何分割成数据块的,以及这些数据块分别被存储到那些数据节点上,它的主要功能是对内存及IO进行集中管理

Secondary Namenode :辅助后台程序,与Namenode进行通信,以便定期保存HDFS元数据的快照,用以备份和恢复数据。

HDFS-API-Fsimage和Edits解析

  1. Fsinmage文件:HDFS文件系统元数据的一个永久性的检查点,其中包含所有目录和文件的inode序列化信息。
  2. Edits文件:存放HDFS文件系统的所有更新操作的路径,文件系统客户端的所有写操作首先会被记录到Edits文件中。
  3. seen-exid文件保存的是一个数字,就是最后一个edits-的数字。
  4. 每次NameNode启动的时候都会将Fsimage文件读入内存,加载Edits里面的更新操作,保证内存中的元数据信息是最新的、同步的,可以看成NameNode启动的时候就将Fsimage和Edits文件进行了合并。

六、Datanode工作机制(了解底层原理)

A、工作机制

(图片来自尚硅谷) 

B、Fsimage和Edits解析

 一、oiv查看Fsimage文件

  1.        查看oiv和oev命令
    [atguigu@hadoop102 current]$ hdfs
    oiv            apply the offline fsimage viewer to an fsimage
    oev            apply the offline edits viewer to an edits file

  2. 基本语法

    hdfs oiv -p 文件类型 -i镜像文件 -o 转换后文件输出路径

  3. 下载到win电脑

  4. 在win系统中查看 

 二、oev查看Edits文件

基本语法

hdfs oev -p 文件类型 -i编辑日志 -o 转换后文件输出路径

C、CheckPoint时间设置

  1. 通常情况下:SecondaryNameNode每隔一小时执行一次
  2. 一分钟检查一次操作次数,当操作次数达到1百万次时,SecondaryNameNode就执行一次。

1)第一阶段:NameNode启动

(1)第一次启动NameNode格式化后,创建Fsimage和Edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存。

(2)客户端对元数据进行增删改的请求。

(3)NameNode记录操作日志,更新滚动日志。

(4)NameNode在内存中对元数据进行增删改。

2)第二阶段:Secondary NameNode工作

(1)Secondary NameNode询问NameNode是否需要CheckPoint。直接带回NameNode是否检查结果。

(2)Secondary NameNode请求执行CheckPoint。

(3)NameNode滚动正在写的Edits日志。

(4)将滚动前的编辑日志和镜像文件拷贝到Secondary NameNode。

(5)Secondary NameNode加载编辑日志和镜像文件到内存,并合并。

(6)生成新的镜像文件fsimage.chkpoint。

(7)拷贝fsimage.chkpoint到NameNode。

(8)NameNode将fsimage.chkpoint重新命名成fsimage。

D、掉线时参数设置

  1. DataNode进程死亡或者网络故障造成DataNode无法与NameNode通信
  2. NameNode不会立即把该节点判断为死亡,要经过一段时间,这段时间暂称作超时时长
  3. HDFS默认的操作时长为10分钟+30秒
  4. 如果定义时间为TimeOut,则超时时长的计算公式为:TimeOut = 2*dfs.namenodleheatbeat.interval.而默认的是hdfs-site。xml配置的文件中的hearbeat.recheck.interval大小为5分钟,dfs.heartbeat.interval.
  5. 需要注意的是hdfs-site-xml配置的文件中的beartbeat。recheck.interval的单位为毫秒,dfs.heartbeat.interval的单位为秒。
    <property>
        <name>dfs.namenode.heartbeat.recheck-interval</name>
        <value>300000</value>
    </property>
    
    <property>
        <name>dfs.heartbeat.interval</name>
        <value>3</value>
    </property>
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值