Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

大数据技术之_04_Hadoop学习_01_HDFS_HDFS概述+HDFS的Shell操作(开发重点)+HDFS客户端操作(开发重点)+HDFS的数据流(面试重点)+NameNode和SecondaryNameNode(面试开发重点)

黑泽君 2019-02-05 22:48:00 阅读数:233 评论数:0 点赞数:0 收藏数:0

第1章 HDFS概述1.1 HDFS产出背景及定义1.2 HDFS优缺点1.3 HDFS组成架构1.4 HDFS文件块大小(面试重点)第2章 HDFS的Shell操作(开发重点)第3章 HDFS客户端操作(开发重点)3.1 HDFS客户端环境准备3.2 HDFS的API操作3.2.1 HDFS文件上传(测试参数优先级)3.2.2 HDFS文件下载3.2.3 HDFS文件夹删除3.2.4 HDFS文件名更改3.2.5 HDFS文件详情查看3.2.6 HDFS文件和文件夹判断3.3 HDFS的I/O流操作(自定义框架使用)3.3.1 HDFS文件上传3.3.2 HDFS文件下载3.3.3 定位文件读取第4章 HDFS的数据流(面试重点)4.1 HDFS写数据流程4.1.1 剖析文件写入4.1.2 网络拓扑-节点距离计算4.1.3 机架感知(副本存储节点选择)4.2 HDFS读数据流程第5章 NameNode和SecondaryNameNode(面试开发重点)5.1 NN和2NN工作机制5.2 Fsimage和Edits解析5.3 CheckPoint时间设置5.4 NameNode故障处理(开发重点:偏运维)5.5 集群安全模式5.6 NameNode多目录配置

第1章 HDFS概述

1.1 HDFS产出背景及定义

其他文件管理系统:

1.2 HDFS优缺点

优点缺点

1.3 HDFS组成架构

1)NameNode(nn)和DataNode(dn)2)Client和Secondary NameNode(2nn)

1.4 HDFS文件块大小(面试重点)

思考:为什么块的大小不能设置太小,也不能设置太大?传统硬盘HDD(Hard Disk Drive)传输速率:100MB/s固态硬盘SSD(Solid State Drive)传输速率:500MB/s混合硬盘HHD(Hybrid Harddrive)传输速率:300MB/sPCIe固态硬盘SSD(Solid State Drive)传输速率:1500MB/s

第2章 HDFS的Shell操作(开发重点)

1、基本语法bin/hadoop fs 具体命令 OR bin/hdfs dfs 具体命令dfs是fs的实现类。2、命令大全[[atguigu@hadoop102 hadoop-2.7.2]$ bin/hadoop fs Usage: hadoop fs [generic options]     [-appendToFile  ... ]     [-cat [-ignoreCrc]  ...]     [-checksum  ...]     [-chgrp [-R] GROUP PATH...]     [-chmod [-R]  PATH...]     [-chown [-R] [OWNER][:[GROUP]] PATH...]     [-copyFromLocal [-f] [-p] [-l]  ... ]     [-copyToLocal [-p] [-ignoreCrc] [-crc]  ... ]     [-count [-q] [-h]  ...]     [-cp [-f] [-p | -p[topax]]  ... ]     [-createSnapshot  []]     [-deleteSnapshot  ]     [-df [-h] [ ...]]     [-du [-s] [-h]  ...]     [-expunge]     [-find  ...  ...]     [-get [-p] [-ignoreCrc] [-crc]  ... ]     [-getfacl [-R] ]     [-getfattr [-R] {-n name | -d} [-e en] ]     [-getmerge [-nl]  ]     [-help [cmd ...]]     [-ls [-d] [-h] [-R] [ ...]]     [-mkdir [-p]  ...]     [-moveFromLocal  ... ]     [-moveToLocal  ]     [-mv  ... ]     [-put [-f] [-p] [-l]  ... ]     [-renameSnapshot   ]     [-rm [-f] [-r|-R] [-skipTrash]  ...]     [-rmdir [--ignore-fail-on-non-empty] 

 ...]     [-setfacl [-R] [{-b|-k} {-m|-x ]|[--set  ]]     [-setfattr {-n name [-v value] | -x name} ]     [-setrep [-R] [-w]   ...]     [-stat [format]  ...]     [-tail [-f] ]     [-test -[defsz] ]     [-text [-ignoreCrc]  ...]     [-touchz  ...]     [-truncate [-w]   ...]     [-usage [cmd ...]] Generic options supported are -conf      specify an application configuration file -D             use value for given property -fs       specify a namenode -jt     specify a ResourceManager -files     specify comma separated files to be copied to the map reduce cluster -libjars     specify comma separated jar files to include in the classpath. -archives     specify comma separated archives to be unarchived on the compute machines. The general command line syntax is bin/hadoop command [genericOptions] [commandOptions] [atguigu@hadoop102 hadoop-2.7.2]$ 

3.常用命令实操(0)启动Hadoop集群(方便后续的测试)

[atguigu@hadoop102 hadoop-2.7.2]$ sbin/start-dfs.sh [atguigu@hadoop103 hadoop-2.7.2]$ sbin/start-yarn.sh

(1)-help:输出这个命令参数

[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -help rm

(2)-ls: 显示目录信息

[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -ls /

(3)-mkdir:在HDFS上创建目录

[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -mkdir -p /sanguo/shuguo/

(4)-moveFromLocal:从本地系统中剪切粘贴文件到HDFS上(本地系统中不存在该文件)

[atguigu@hadoop102 hadoop-2.7.2]$ touch kongming.txt [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -moveFromLocal ./kongming.txt /sanguo/shuguo/

(5)-appendToFile:追加一个文件到已经存在的文件末尾

[atguigu@hadoop102 hadoop-2.7.2]$ touch liubei.txt [atguigu@hadoop102 hadoop-2.7.2]$ vim liubei.txt 输入 san gu mao lu [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -appendToFile liubei.txt /sanguo/shuguo/kongming.txt

(6)-cat:显示文件内容

[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -cat /sanguo/shuguo/kongming.txt

(7)-chgrp 、-chmod、-chown:跟Linux文件系统中的用法一样,修改文件所属权限

[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -chmod 666 /sanguo/shuguo/kongming.txt [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -chown atguigu:atguigu /sanguo/shuguo/kongming.txt

(8)-copyFromLocal:从本地文件系统中拷贝文件到HDFS路径中去(本地系统中还存在该文件)

[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -copyFromLocal README.txt /

(9)-copyToLocal:从HDFS拷贝到本地系统中

[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -copyToLocal /sanguo/shuguo/kongming.txt ./

(10)-cp:从HDFS的一个路径拷贝到HDFS的另一个路径(文件还在旧的HDFS中)

[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -cp /sanguo/shuguo/kongming.txt /zhuge.txt

(11)-mv:在HDFS目录中移动文件(文件不在旧的HDFS中,在新的HDFS中)

[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -mv /zhuge.txt /sanguo/shuguo/

(12)-get:等同于copyToLocal,就是从HDFS下载文件到本地系统中

[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -get /sanguo/shuguo/kongming.txt ./

(13)-getmerge:合并下载多个文件,比如HDFS的目录 /user/atguigu/test/ 下有多个文件:log.1,log.2,log.3,……

[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -getmerge /sanguo/shuguo//* ./zaiyiqi.txt

(14)-put:等同于copyFromLocal,就是从本地文件系统中拷贝文件到HDFS路径中去

[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -put ./zaiyiqi.txt /sanguo/shuguo/

(15)-tail:显示一个文件的末尾几行(因为日志文件一般是在文件的末尾不断地追加,即监控新产生的数据变化)

[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -tail /sanguo/shuguo/kongming.txt

(16)-rm:删除文件或文件夹

[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -rm /sanguo/shuguo/zaiyiqi.txt

(17)-rmdir:删除空目录

[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -mkdir /test [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -rmdir /test

(18)-du:统计文件夹的大小信息

[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -du -s -h /user/atguigu/test/ 2.7 K  /user/atguigu/test [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -du -h /user/atguigu/test/ 1.3 K  /user/atguigu/test/README.txt 1.4 K  /user/atguigu/test/zaiyiqi.txt

(19)-setrep:设置HDFS中文件的副本数量

[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -setrep 10 /kongming.txt

HDFS副本数量

这里设置的副本数只是记录在NameNode的元数据中,是否真的会有这么多副本,还得看DataNode的数量。因为目前只有3台设备,最多也就3个副本,只有节点数的增加到10台时,副本数才能达到10。

第3章 HDFS客户端操作(开发重点)

3.1 HDFS客户端环境准备

1、根据自己电脑的操作系统拷贝对应的编译后的hadoop jar包到非中文路径(例如:D:Develophadoop-2.7.2),如下图所示。2、配置HADOOP_HOME环境变量,如下图所示:3、配置Path环境变量,如下图所示:4、创建一个Maven工程HdfsClientDemo5、导入相应的依赖坐标+日志添加              junit         junit         RELEASE                       org.apache.logging.log4j         log4j-core         2.8.2                   org.apache.hadoop         hadoop-common         2.7.2                   org.apache.hadoop         hadoop-client         2.7.2                   org.apache.hadoop         hadoop-hdfs         2.7.2                   jdk.tools         jdk.tools         1.8         system         ${JAVA_HOME}/lib/tools.jar     

注意:如果Eclipse/Idea打印不出日志,在控制台上只显示

1.log4j:WARN No appenders could be found for logger (org.apache.hadoop.util.Shell).   2.log4j:WARN Please initialize the log4j system properly.   3.log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html/#noconfig for more info.

需要在项目的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

6、创建包名:com.atguigu.hdfs7、创建HdfsClient类

public class HdfsClient {     ///      / 测试创建多级文件夹:在hdfs系统上创建多级文件夹      //     @Test     public void testMkdirs() throws IOException, InterruptedException, URISyntaxException {         // 1、获取hdfs文件系统对象         Configuration configuration = new Configuration();         // 配置在集群上运行         configuration.set("fs.defaultFS", "hdfs://hadoop102:9000");         FileSystem fs = FileSystem.get(configuration);         // 2 、创建目录         fs.mkdirs(new Path("/0529/dashen"));         // 3 、关闭资源         fs.close();     } }

8、执行程序运行时需要配置用户名称,右键 -> Run Configurations,如下图所示:

客户端去操作HDFS时,是有一个用户身份的。默认情况下,HDFS客户端API会从JVM中获取一个参数来作为自己的用户身份:-DHADOOPUSERNAME=atguigu,atguigu为用户名称。9、另一种【配置在集群上运行】的方式,可以不用手动配置用户名称public class HdfsClient {     ///      / 测试创建多级文件夹:在hdfs系统上创建多级文件夹      //     @Test     public void testMkdirs() throws IOException, InterruptedException, URISyntaxException {         // 1、 获取hdfs文件系统对象         Configuration configuration = new Configuration();         // 配置在集群上运行         // configuration.set("fs.defaultFS", "hdfs://hadoop102:9000");         // FileSystem fs = FileSystem.get(configuration);         FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");         // 2 、创建目录         fs.mkdirs(new Path("/0529/dashen"));         // 3 、关闭资源         fs.close();     } }

3.2 HDFS的API操作

3.2.1 HDFS文件上传(测试参数优先级)

1、编写源代码    ///      / 测试文件上传:从本地系统上传文件至hdfs文件系统上      //     @Test     public void testCopyFromLocalFile() throws IOException, InterruptedException, URISyntaxException {         Configuration configuration = new Configuration();         // 1、获取hdfs文件系统         FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");         configuration.set("dfs.replication", "2");         // 2、本地系统执行上传文件操作         fs.copyFromLocalFile(new Path("D:/temp/atguigu/0529/banzhang.txt"), new Path("/banzhang.txt"));         // 3、关闭资源         fs.close();     }

2、在/HdfsClientDemo/src/main/resources/目录下新建hdfs-site.xml文件,文件内容如下,然后再次执行上传文件操作

             dfs.replication                  1     

3.参数优先级参数优先级排序:(1)客户端代码中设置的值 >(2)ClassPath下的用户自定义配置文件设置的值 >(3)hdfs服务器的默认配置的值

效果如下图所示:

3.2.2 HDFS文件下载

示例代码如下:    ///      / 测试文件下载:将hdfs文件系统上的文件下载到本地系统上      //     @Test     public void testCopyToLocalFile() throws IOException, InterruptedException, URISyntaxException {         Configuration configuration = new Configuration();         // 1、获取hdfs文件系统对象         FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");         // 2、执行下载文件操作         // fs.copyToLocalFile(new Path("/banhua.txt"), new Path("D:/temp/atguigu/0529/banhua.txt"));         // boolean delSrc 指是否将源文件删除,默认值是false,表示不删除源文件         // Path src 指要下载的文件路径         // Path dst 指将文件下载到的路径         // boolean useRawLocalFileSystem 是否开启文件校验,即是否生成 .xxx.crc 检验文件,默认值是false,表示生成检验文件         fs.copyToLocalFile(false, new Path("/bancao.txt"), new Path("D:/temp/atguigu/0529/bancao.txt"), true);         // 3、关闭资源         fs.close();     }

3.2.3 HDFS文件夹删除

示例代码如下:    ///      / 测试[文件夹/文件]删除:将hdfs文件系统上的[文件夹/文件]删除      //     @Test     public void testDelete() throws IOException, InterruptedException, URISyntaxException {         Configuration configuration = new Configuration();         // 1、获取hdfs文件系统对象         FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");         // 2、执行删除文件操作         // boolean recursive 指的是递归的意思,设置成true,表示递归删除文件夹         fs.delete(new Path("/0529/"), true);         // 3、关闭资源         fs.close();     }

3.2.4 HDFS文件名更改

示例代码如下:    ///      / 文件名更改:将hdfs文件系统上的文件更改名称      //     @Test     public void testRename() throws IOException, InterruptedException, URISyntaxException {         Configuration configuration = new Configuration();         // 1、获取hdfs文件系统对象         FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");         // 2、执行文件名更改操作         fs.rename(new Path("/banzhang.txt"), new Path("/yanjing.txt"));         // 3、关闭资源         fs.close();     }

3.2.5 HDFS文件详情查看

查看文件名称、权限、长度、块信息示例代码如下:    ///      / 查看文件详情      //     @Test     public void testListFiles() throws IOException, InterruptedException, URISyntaxException {         Configuration configuration = new Configuration();         // 1、获取hdfs文件系统对象         FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");         // 2、获取文件详情         RemoteIterator listFiles = fs.listFiles(new Path("/"), true);         while (listFiles.hasNext()) {             LocatedFileStatus fileStatus = listFiles.next();             // 输出详情             System.out.println(fileStatus.getPath().getName()); // 文件名称             System.out.println(fileStatus.getPermission()); // 权限             System.out.println(fileStatus.getLen()); // 长度             System.out.println(fileStatus.getGroup()); // 分组             // 获取存储的块信息             BlockLocation[] blockLocations = fileStatus.getBlockLocations();             for (BlockLocation blockLocation : blockLocations) {                 // 获取块存储的主机节点                 String[] hosts = blockLocation.getHosts();                 for (String host : hosts) {                     System.out.println(host);                 }             }             System.out.println("---------------------");         }         // 3、关闭资源         fs.close();     }

3.2.6 HDFS文件和文件夹判断

示例代码如下:    ///      / 判断是文件还是文件夹      //     @Test     public void testListStatus() throws IOException, InterruptedException, URISyntaxException {         Configuration configuration = new Configuration();         // 1、获取hdfs文件系统对象         FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");         // 2、判断是文件还是文件夹         FileStatus[] listStatus  = fs.listStatus(new Path("/"));         for (FileStatus fileStatus : listStatus) {             // 如果是文件             if (fileStatus.isFile()) {                 System.out.println("f:" + fileStatus.getPath().getName());             } else {                 System.out.println("d:" + fileStatus.getPath().getName());             }         }         // 3、关闭资源         fs.close();     }

3.3 HDFS的I/O流操作(自定义框架使用)

上面我们学的API操作HDFS系统都是框架封装好的。那么如果我们想自己实现上述API的操作该怎么实现呢?我们可以采用IO流的方式实现数据的上传和下载。

3.3.1 HDFS文件上传

1、需求:把本地

D:tempatguigu0529上的banhua.txt文件上传到HDFS根目录2、编写代码    ///      / 把本地 D:tempatguigu0529 上的banhua.txt文件上传到HDFS根目录      //     @Test     public void putFileToHDFS() throws IOException, InterruptedException, URISyntaxException {         // 1、获取hdfs文件系统对象         Configuration configuration = new Configuration();         FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");         // 2、创建输入流         FileInputStream fis = new FileInputStream(new File("D:/temp/atguigu/0529/banhua.txt"));         // 3、创建输出流         FSDataOutputStream fos = fs.create(new Path("/banzhang.txt"));         // 4、流对拷         IOUtils.copyBytes(fis, fos, configuration);         // 5、关闭资源         IOUtils.closeStream(fos);         IOUtils.closeStream(fis);         fs.close();     }

3.3.2 HDFS文件下载

1、需求:从HDFS上下载banhua.txt文件到本地

D:tempatguigu0529上2、编写代码     / 从HDFS上下载banhua.txt文件到本地 D:tempatguigu0529 上      //     @Test     public void getFileFromHDFS() throws IOException, InterruptedException, URISyntaxException {         // 1、获取hdfs文件系统对象         Configuration configuration = new Configuration();         FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");         // 2、创建输入流         FSDataInputStream fis = fs.open(new Path("/banhua.txt"));         // 3、创建输出流         FileOutputStream fos = new FileOutputStream(new File("D:/temp/atguigu/0529/banhua.txt"));         // 4、流对拷         IOUtils.copyBytes(fis, fos, configuration);         // 5、关闭资源         IOUtils.closeStream(fos);         IOUtils.closeStream(fis);         fs.close();     }

3.3.3 定位文件读取

1、需求:分块读取HDFS上的大文件,比如根目录下的/hadoop-2.7.2.tar.gz2、编写代码(1)下载第一块    ///      / 分块读取HDFS上的大文件,比如根目录下的/hadoop-2.7.2.tar.gz,下载第一块      //     @Test     public void readFileSeek1() throws IOException, InterruptedException, URISyntaxException {         // 1、获取hdfs文件系统对象         Configuration configuration = new Configuration();         FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");         // 2、获取输入流         FSDataInputStream fis = fs.open(new Path("/hadoop-2.7.2.tar.gz"));         // 3、创建输出流         FileOutputStream fos = new FileOutputStream(new File("D:/temp/atguigu/0529/hadoop-2.7.2.tar.gz.part1"));         // 4、流的对拷         byte[] buf = new byte[1024];         for (int i = 0; i < 1024 /* 128; i++) {             fis.read(buf);             fos.write(buf);         }         // 5、关闭资源         IOUtils.closeStream(fis);         IOUtils.closeStream(fos);         fs.close();     }

(2)下载第二块

    ///      / 分块读取HDFS上的大文件,比如根目录下的/hadoop-2.7.2.tar.gz,下载第二块      //     @Test     public void readFileSeek2() throws IOException, InterruptedException, URISyntaxException {         // 1、获取hdfs文件系统对象         Configuration configuration = new Configuration();         FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");         // 2、获取输入流         FSDataInputStream fis = fs.open(new Path("/hadoop-2.7.2.tar.gz"));         // 3、定位输入数据位置         fis.seek(1024/1024/128);         // 4、创建输出流         FileOutputStream fos = new FileOutputStream(new File("D:/temp/atguigu/0529/hadoop-2.7.2.tar.gz.part2"));         // 5、流的对拷         IOUtils.copyBytes(fis, fos, configuration);         // 6、关闭资源         IOUtils.closeStream(fis);         IOUtils.closeStream(fos);         fs.close();     }

(3)合并文件在Window命令窗口中进入到目录 D:tempatguigu0529,然后执行如下命令,对数据进行合并

type hadoop-2.7.2.tar.gz.part2 >> hadoop-2.7.2.tar.gz.part1

合并完成后,将hadoop-2.7.2.tar.gz.part1重新命名为hadoop-2.7.2.tar.gz。解压发现该tar包非常完整。

第4章 HDFS的数据流(面试重点)

4.1 HDFS写数据流程

4.1.1 剖析文件写入

HDFS写数据流程,如下图所示。详解如下:

  • 1)客户端通过Distributed FileSystem模块向NameNode请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在。
  • 2)NameNode返回是否可以上传。
  • 3)客户端请求第一个Block上传到哪几个DataNode服务器上。
  • 4)NameNode返回3个DataNode节点,分别为dn1、dn2、dn3。
  • 5)客户端通过FSDataOutputStream模块请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成。
  • 6)dn1、dn2、dn3逐级应答客户端。
  • 7)客户端开始往dn1上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以Packet为单位,dn1收到一个Packet就会传给dn2,dn2传给dn3;dn1每传一个packet会放入一个应答队列等待应答。
  • 8)当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器。(重复执行3-7步)。

4.1.2 网络拓扑-节点距离计算

在HDFS写数据的过程中,NameNode会选择距离待上传数据最近距离的DataNode接收数据。那么这个最近距离怎么计算呢?

节点距离:两个节点到达最近的共同祖先的距离总和。网络拓扑概念:例如,假设有数据中心d1机架r1中的节点n1。该节点可以表示为/d1/r1/n1。利用这种标记,这里给出四种距离描述,如上图所示。大家算一算每两个节点之间的距离,如下图所示。

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

1、官方ip地址机架感知说明:http://hadoop.apache.org/docs/r2.7.2/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html/#Data_ReplicationFor the common case, when the replication factor is three, HDFS’s placement policy is to put one replica on one node in the local rack, another on a different node in the local rack, and the last on a different node in a different rack. This policy cuts the inter-rack write traffic which generally improves write performance. The chance of rack failure is far less than that of node failure; this policy does not impact data reliability and availability guarantees. However, it does reduce the aggregate network bandwidth used when reading data since a block is placed in only two unique racks rather than three. With this policy, the replicas of a file do not evenly distribute across the racks. One third of replicas are on one node, two thirds of replicas are on one rack, and the other third are evenly distributed across the remaining racks. This policy improves write performance without compromising data reliability or read performance.

翻译如下:

对于常见情况,当复制因子为3时,HDFS的放置策略是将一个副本放在本地机架中的一个节点上,另一个放在本地机架中的另一个节点上,将最后一个放在另一个机架中的另一个节点上。此策略可以减少机架间写入流量,从而提高写入性能。机架故障的可能性远小于节点故障的可能性; 此策略不会影响数据可靠性和可用性保证。但是,它确实减少了读取数据时使用的聚合网络带宽,因为块只放在两个唯一的机架而不是三个。使用此策略时,文件的副本不会均匀分布在机架上。三分之一的副本位于一个节点上,三分之二的副本位于一个机架上,另外三个副本均匀分布在剩余的机架上。

2、Hadoop2.7.2副本节点选择

4.2 HDFS读数据流程

HDFS的读数据流程,如下图所示。详解如下:

  • 1)客户端通过Distributed FileSystem向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址。
  • 2)挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据。
  • 3)DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)。
  • 4)客户端以Packet为单位接收,先在本地缓存,然后写入目标文件。

第5章 NameNode和SecondaryNameNode(面试开发重点)

5.1 NN和2NN工作机制

思考:NameNode中的元数据是存储在哪里的?首先,我们做个假设,如果存储在NameNode节点的磁盘中,因为经常需要进行随机访问,还有响应客户请求,必然是效率过低。因此,元数据需要存放在内存中。但如果只存在内存中,一旦断电,元数据丢失,整个集群就无法工作了。

因此产生在磁盘中备份元数据的FsImage。这样又会带来新的问题,当在内存中的元数据更新时,如果同时更新FsImage,就会导致效率过低,但如果不更新,就会发生一致性问题,一旦NameNode节点断电,就会产生数据丢失。

因此,引入Edits文件(只进行追加操作,效率很高)。每当元数据有更新或者添加元数据时,修改内存中的元数据并追加到Edits中。这样,一旦NameNode节点断电,可以通过FsImage和Edits的合并,合成元数据。但是,如果长时间添加数据到Edits中,会导致该文件数据过大,效率降低,而且一旦断电,恢复元数据需要的时间过长。因此,需要定期进行FsImage和Edits的合并,如果这个操作由NameNode节点完成,又会效率过低。

因此,引入一个新的节点SecondaryNamenode,专门用于FsImage和Edits的合并。NN和2NN工作机制,如下图所示。详解如下: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。NN和2NN工作机制详解:Fsimage:NameNode内存中元数据序列化后形成的文件。Edits:记录客户端更新元数据信息的每一步操作(可通过Edits运算出元数据)。NameNode启动时,先滚动Edits并生成一个空的edits.inprogress,然后加载Edits和Fsimage到内存中,此时NameNode内存就持有最新的元数据信息。Client开始对NameNode发送元数据的增删改的请求,这些请求的操作首先会被记录到edits.inprogress中(查询元数据的操作不会被记录在Edits中,因为查询操作不会更改元数据信息),如果此时NameNode挂掉,重启后会从Edits中读取元数据的信息。然后,NameNode会在内存中执行元数据的增删改的操作。由于Edits中记录的操作会越来越多,Edits文件会越来越大,导致NameNode在启动加载Edits时会很慢,所以需要对Edits和Fsimage进行合并(所谓合并,就是将Edits和Fsimage加载到内存中,照着Edits中的操作一步步执行,最终形成新的Fsimage)。SecondaryNameNode的作用就是帮助NameNode进行Edits和Fsimage的合并工作。SecondaryNameNode首先会询问NameNode是否需要CheckPoint(触发CheckPoint需要满足两个条件中的任意一个,定时时间到和Edits中数据写满了)。直接带回NameNode是否检查结果。SecondaryNameNode执行CheckPoint操作,首先会让NameNode滚动Edits并生成一个空的edits.inprogress,滚动Edits的目的是给Edits打个标记,以后所有新的操作都写入edits.inprogress,其他未合并的Edits和Fsimage会拷贝到SecondaryNameNode的本地,然后将拷贝的Edits和Fsimage加载到内存中进行合并,生成fsimage.chkpoint,然后将fsimage.chkpoint拷贝给NameNode,重命名为Fsimage后替换掉原来的Fsimage。NameNode在启动时就只需要加载之前未合并的Edits和Fsimage即可,因为合并过的Edits中的元数据信息已经被记录在Fsimage中。

 

5.2 Fsimage和Edits解析

1、概念

2、oiv查看Fsimage文件(1)查看oiv和oev命令

[atguigu@hadoop102 current]$ hdfs Usage: hdfs [--config confdir] [--loglevel loglevel] COMMAND        where COMMAND is one of:   dfs                  run a filesystem command on the file systems supported in Hadoop.   classpath            prints the classpath   namenode -format     format the DFS filesystem   secondarynamenode    run the DFS secondary namenode   namenode             run the DFS namenode   journalnode          run the DFS journalnode   zkfc                 run the ZK Failover Controller daemon   datanode             run a DFS datanode   dfsadmin             run a DFS admin client   haadmin              run a DFS HA admin client   fsck                 run a DFS filesystem checking utility   balancer             run a cluster balancing utility   jmxget               get JMX exported values from NameNode or DataNode.   mover                run a utility to move block replicas across                        storage types   oiv                  apply the offline fsimage viewer to an fsimage   oiv_legacy           apply the offline fsimage viewer to an legacy fsimage   oev                  apply the offline edits viewer to an edits file   fetchdt              fetch a delegation token from the NameNode   getconf              get config values from configuration   groups               get the groups which users belong to   snapshotDiff         diff two snapshots of a directory or diff the                        current directory contents with a snapshot   lsSnapshottableDir   list all snapshottable dirs owned by the current user                         Use -help to see options   portmap              run a portmap service   nfs3                 run an NFS version 3 gateway   cacheadmin           configure the HDFS cache   crypto               configure HDFS encryption zones   storagepolicies      list/get/set block storage policies   version              print the version Most commands print help when invoked w/o parameters. [atguigu@hadoop102 current]$ 

(2)基本语法hdfs oiv -p 文件类型 -i 镜像文件 -o 转换后文件输出路径(3)案例实操

[atguigu@hadoop102 current]$ pwd /opt/module/hadoop-2.7.2/data/tmp/dfs/name/current [atguigu@hadoop102 current]$ hdfs oiv -p XML -i fsimage_0000000000000000124 -o fsimage.xml [atguigu@hadoop102 current]$ cat fsimage.xml 

将显示的xml文件内容拷贝到Eclipse中创建的xml文件中,并格式化。部分显示结果如下。

    16385     DIRECTORY          1549193480818     atguigu:supergroup:rwxr-xr-x     9223372036854775807     -1     16386     FILE     wc.input     3     1549109263472     1549191451377     134217728     atguigu:supergroup:rw-r--r--                           1073741825             1001             43                   16394     FILE     kongming.txt     10     1549172409335     1549172409063     134217728     atguigu:supergroup:rw-r--r--                           1073741832             1009             28                   16398     FILE     yanjing.txt     3     1549182842815     1549191453687     134217728     atguigu:supergroup:rw-r--r--                           1073741833             1010             29                   16399     FILE     banhua.txt     1     1549183347279     1549191440485     134217728     atguigu:supergroup:rw-r--r--                           1073741834             1011             29                   16400     FILE     bancao.txt     2     1549183571406     1549191438143     134217728     atguigu:supergroup:rw-r--r--                           1073741835             1012             29                   16401     FILE     banzhang.txt     1     1549192955364     1549192955243     134217728     atguigu:supergroup:rw-r--r--                           1073741836             1013             12                   16402     FILE     hadoop-2.7.2.tar.gz     3     1549193480811     1549193471067     134217728     atguigu:supergroup:rw-r--r--                           1073741837             1014             134217728                               1073741838             1015             63439959              

思考:可以看出,Fsimage中没有记录块所对应DataNode,为什么?答:是因为在集群启动后,要求DataNode上报数据块信息,并间隔一段时间后再次上报。所以我们要先启动集群。

3、oev查看Edits文件(1)基本语法hdfs oev -p 文件类型 -i 编辑日志 -o 转换后文件输出路径(2)案例实操[atguigu@hadoop102 current]$ hdfs oev -p XML -i edits_0000000000000000103-0000000000000000108 -o edits.xml [atguigu@hadoop102 current]$ cat edits.xml

将显示的xml文件内容拷贝到Eclipse中创建的xml文件中,并格式化。显示结果如下。

    VERSION>-63VERSION>              OPSTARTLOGSEGMENT                      103                            OPTIMES                      104             0             /bancao.txt             -1             1549191438143                            OPTIMES                      105             0             /banhua.txt             -1             1549191440485                            OPTIMES                      106             0             /wc.input             -1             1549191451377                            OPTIMES                      107             0             /yanjing.txt             -1             1549191453687                            OPENDLOGSEGMENT                      108              

思考:NameNode如何确定下次开机启动的时候合并哪些Edits?答:根据

seen_txid里面记录最新的

Fsimage(镜像文件)的值去合并

Edits(编辑日志)。

5.3 CheckPoint时间设置

(1)通常情况下,SecondaryNameNode每隔一小时执行一次。[hdfs-default.xml]     dfs.namenode.checkpoint.period     3600     SecondaryNameNode每隔一小时执行一次

(2)当操作次数达到1百万时,SecondaryNameNode执行一次。

    dfs.namenode.checkpoint.txns     1000000     操作动作次数

(3)一分钟检查一次操作次数。

    dfs.namenode.checkpoint.check.period     60     1分钟检查一次操作次数

该文件截图如下:

5.4 NameNode故障处理(开发重点:偏运维)

NameNode故障后,可以采用如下两种方法恢复数据。

方法一:将SecondaryNameNode中数据拷贝到NameNode存储数据的目录。1、kill -9 NameNode进程2、删除NameNode存储的数据目录中的数据(目录位置:/opt/module/hadoop-2.7.2/data/tmp/dfs/name/)[atguigu@hadoop102 hadoop-2.7.2]$ rm -rf /opt/module/hadoop-2.7.2/data/tmp/dfs/name//*

3、拷贝SecondaryNameNode中数据到原NameNode存储数据目录

[atguigu@hadoop102 name]$ pwd /opt/module/hadoop-2.7.2/data/tmp/dfs/name [atguigu@hadoop102 name]$ scp -r atguigu@hadoop104:/opt/module/hadoop-2.7.2/data/tmp/dfs/namesecondary//* ./

4、重新启动NameNode

[atguigu@hadoop102 hadoop-2.7.2]$ sbin/hadoop-daemon.sh start namenode

**方法二:使用

-importCheckpoint选项启动NameNode守护进程,从而将SecondaryNameNode中数据拷贝到NameNode目录中。**1、修改hdfs-site.xml中的内容,新增如下,然后分发到其他节点

[atguigu@hadoop102 hadoop-2.7.2]$ vim etc/hadoop/hdfs-site.xml     dfs.namenode.checkpoint.period     120     dfs.namenode.name.dir     /opt/module/hadoop-2.7.2/data/tmp/dfs/name/ [atguigu@hadoop102 hadoop-2.7.2]$ xsync etc/hadoop/

2、kill -9 NameNode进程3、删除NameNode存储的数据目录中的数据(目录位置:/opt/module/hadoop-2.7.2/data/tmp/dfs/name/)

[atguigu@hadoop102 hadoop-2.7.2]$ rm -rf /opt/module/hadoop-2.7.2/data/tmp/dfs/name//*

4、如果SecondaryNameNode不和NameNode在一个主机节点上,需要将

SecondaryNameNode存储数据的目录namesecondary拷贝到

NameNode存储数据的平级目录name,并删除in_use.lock文件

[atguigu@hadoop102 dfs]$ pwd /opt/module/hadoop-2.7.2/data/tmp/dfs [atguigu@hadoop102 dfs]$ ll 总用量 8 drwx------. 3 atguigu atguigu 4096 2月   4 10:37 data drwxrwxr-x. 2 atguigu atguigu 4096 2月   4 10:59 name [atguigu@hadoop102 dfs]$ scp -r atguigu@hadoop104:/opt/module/hadoop-2.7.2/data/tmp/dfs/namesecondary/ ./ [atguigu@hadoop102 dfs]$ ll 总用量 12 drwx------. 3 atguigu atguigu 4096 2月   4 10:37 data drwxrwxr-x. 2 atguigu atguigu 4096 2月   4 10:59 name drwxrwxr-x. 3 atguigu atguigu 4096 2月   4 11:04 namesecondary [atguigu@hadoop102 dfs]$ [atguigu@hadoop102 dfs]$ rm -rf namesecondary/in_use.lock 

5、导入检查点数据(设置的是2分钟,等待一会ctrl+c结束掉)

[atguigu@hadoop102 hadoop-2.7.2]$ bin/hdfs namenode -importCheckpoint

6、启动NameNode

[atguigu@hadoop102 hadoop-2.7.2]$ sbin/hadoop-daemon.sh start namenode

方式二比方式一要检查的东西多一些,方式一比较直接。

5.5 集群安全模式

1、概述

2、基本语法集群处于安全模式,不能执行重要操作(写操作)。集群启动完成后,自动退出安全模式。(1)bin/hdfs dfsadmin -safemode get (功能描述:[查看/获取]安全模式状态)(2)bin/hdfs dfsadmin -safemode enter (功能描述:[进入/开启]安全模式状态)(3)bin/hdfs dfsadmin -safemode leave (功能描述:[离开]安全模式状态)(4)bin/hdfs dfsadmin -safemode wait (功能描述:[等待]安全模式状态)演示如下图所示:

3、案例模拟等待安全模式(1)查看当前模式(2)先进入安全模式(3)创建并执行下面的脚本在/opt/module/hadoop-2.7.2路径上,编辑一个脚本safemode.sh

[atguigu@hadoop102 hadoop-2.7.2]$ bin/hdfs dfsadmin -safemode get Safe mode is OFF [atguigu@hadoop102 hadoop-2.7.2]$ bin/hdfs dfsadmin -safemode enter Safe mode is ON [atguigu@hadoop102 hadoop-2.7.2]$ touch safemode.sh [atguigu@hadoop102 hadoop-2.7.2]$ vim safemode.sh  [atguigu@hadoop102 hadoop-2.7.2]$ cat safemode.sh  /#!/bin/bash hdfs dfsadmin -safemode wait hdfs dfs -put /opt/module/hadoop-2.7.2/README.txt / [atguigu@hadoop102 hadoop-2.7.2]$ bash ./safemode.sh 

(4)再打开一个窗口,执行该脚本

[atguigu@hadoop102 hadoop-2.7.2]$ bin/hdfs dfsadmin -safemode leave

(5)观察(a)再观察上一个窗口Safe mode is OFF(b)HDFS集群上已经有上传的数据了。

5.6 NameNode多目录配置

1、NameNode的本地目录可以配置成多个,且每个目录存放内容相同,增加了可靠性。2、具体配置如下:(1)在hdfs-site.xml文件中增加如下内容,保存退出后,然后进行分发操作[atguigu@hadoop102 hadoop-2.7.2]$ vim etc/hadoop/hdfs-site.xml     dfs.namenode.name.dir     file:///${hadoop.tmp.dir}/dfs/name1,file:///${hadoop.tmp.dir}/dfs/name2 [atguigu@hadoop102 hadoop-2.7.2]$ xsync etc/hadoop/

(2)停止集群,删除data和logs中所有数据。

[atguigu@hadoop102 hadoop-2.7.2]$ sbin/stop-dfs.sh         关闭全部 NameNode 和 DataNode  [atguigu@hadoop103 hadoop-2.7.2]$ sbin/stop-yarn.sh        关闭全部 ResourceManager 和 NodeManager  [atguigu@hadoop102 hadoop-2.7.2]$ rm -rf data/ logs/ [atguigu@hadoop103 hadoop-2.7.2]$ rm -rf data/ logs/ [atguigu@hadoop104 hadoop-2.7.2]$ rm -rf data/ logs/

(3)格式化集群并启动。

[atguigu@hadoop102 hadoop-2.7.2]$ bin/hdfs namenode –format [atguigu@hadoop102 hadoop-2.7.2]$ sbin/start-dfs.sh      开启全部 NameNode 和 DataNode 

(4)查看结果

[atguigu@hadoop102 dfs]$ ll 总用量 8 drwxrwxr-x. 3 atguigu atguigu 4096 2月   4 12:50 name1 drwxrwxr-x. 3 atguigu atguigu 4096 2月   4 12:50 name2 [atguigu@hadoop102 dfs]$ cd name1/ [atguigu@hadoop102 name1]$ cd current/ [atguigu@hadoop102 current]$ ll 总用量 16 -rw-rw-r--. 1 atguigu atguigu 354 2月   4 12:50 fsimage_0000000000000000000 -rw-rw-r--. 1 atguigu atguigu  62 2月   4 12:50 fsimage_0000000000000000000.md5 -rw-rw-r--. 1 atguigu atguigu   2 2月   4 12:50 seen_txid -rw-rw-r--. 1 atguigu atguigu 205 2月   4 12:50 VERSION [atguigu@hadoop102 current]$ cd .. [atguigu@hadoop102 name1]$ cd .. [atguigu@hadoop102 dfs]$ cd name2/ [atguigu@hadoop102 name2]$ cd current/ [atguigu@hadoop102 current]$ ll 总用量 16 -rw-rw-r--. 1 atguigu atguigu 354 2月   4 12:50 fsimage_0000000000000000000 -rw-rw-r--. 1 atguigu atguigu  62 2月   4 12:50 fsimage_0000000000000000000.md5 -rw-rw-r--. 1 atguigu atguigu   2 2月   4 12:50 seen_txid -rw-rw-r--. 1 atguigu atguigu 205 2月   4 12:50 VERSION [atguigu@hadoop102 current]$ cd .. [atguigu@hadoop102 name2]$ cd .. [atguigu@hadoop102 dfs]$ ll 总用量 12 drwx------. 3 atguigu atguigu 4096 2月   4 12:53 data drwxrwxr-x. 3 atguigu atguigu 4096 2月   4 12:53 name1 drwxrwxr-x. 3 atguigu atguigu 4096 2月   4 12:53 name2 [atguigu@hadoop102 dfs]$ ll name1/current/ 总用量 1052 -rw-rw-r--. 1 atguigu atguigu      42 2月   4 12:54 edits_0000000000000000001-0000000000000000002 -rw-rw-r--. 1 atguigu atguigu 1048576 2月   4 12:55 edits_inprogress_0000000000000000003 -rw-rw-r--. 1 atguigu atguigu     354 2月   4 12:50 fsimage_0000000000000000000 -rw-rw-r--. 1 atguigu atguigu      62 2月   4 12:50 fsimage_0000000000000000000.md5 -rw-rw-r--. 1 atguigu atguigu     354 2月   4 12:54 fsimage_0000000000000000002 -rw-rw-r--. 1 atguigu atguigu      62 2月   4 12:54 fsimage_0000000000000000002.md5 -rw-rw-r--. 1 atguigu atguigu       2 2月   4 12:54 seen_txid -rw-rw-r--. 1 atguigu atguigu     205 2月   4 12:50 VERSION [atguigu@hadoop102 dfs]$ ll name2/current/ 总用量 1052 -rw-rw-r--. 1 atguigu atguigu      42 2月   4 12:54 edits_0000000000000000001-0000000000000000002 -rw-rw-r--. 1 atguigu atguigu 1048576 2月   4 12:55 edits_inprogress_0000000000000000003 -rw-rw-r--. 1 atguigu atguigu     354 2月   4 12:50 fsimage_0000000000000000000 -rw-rw-r--. 1 atguigu atguigu      62 2月   4 12:50 fsimage_0000000000000000000.md5 -rw-rw-r--. 1 atguigu atguigu     354 2月   4 12:54 fsimage_0000000000000000002 -rw-rw-r--. 1 atguigu atguigu      62 2月   4 12:54 fsimage_0000000000000000002.md5 -rw-rw-r--. 1 atguigu atguigu       2 2月   4 12:54 seen_txid -rw-rw-r--. 1 atguigu atguigu     205 2月   4 12:50 VERSION [atguigu@hadoop102 dfs]$ 

版权声明
本文为[黑泽君]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/chenmingjun/p/10353274.html

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;

支付宝红包,每日可领