Hadoop-HDFS总结
目录
一、HDFS概述
- HDFS的产生背景和定义
- 随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切的需要一种系统来管理多台机器上的文件,这就是分布式文件管理系统。HDFS只是分布式文件管理系统的一种。
- HDFS定义:HDFS,它是一个文件系统,用于存储文件,通过目录树来定位文件;其次,他是分布式的,有很多服务器联合起来实现其功能,集群中的服务器有各自的角色。 HDFS的使用场景:适合一次写入,多次读出的场景。一个文件经过创建、写入和关闭之后就不需要改变。
- 随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切的需要一种系统来管理多台机器上的文件,这就是分布式文件管理系统。HDFS只是分布式文件管理系统的一种。
- 优缺点:
- 优点:
- 高容错性:数据自动保存多个副本。它通过增加副本的形式,提高容错性。某一个副本丢失后,它可以自动恢复。
- 适合处理大数据:数据规模:能够处理数据规模达到GB、TB、甚至PB级别的数据;文件规模:能过处理百万规模以上的文件数量,数量相当之大。
- 可构建在廉价的机器上,能过多副本机制就,提高可靠性。
- HDFS缺点
- 不适合低延时数据访问,比如毫秒级的存储及数据,是做不到的。
- 无法高效的对大量小文件进行存储。:存储大量小文件的话,它会占用NameNode大量的内存来存储文件目录和快信息。这样是不可取的,因为NameNode的内存总是有限的;小文件存储的寻址时间会超过读取时间,它违反了HDFS的设计目标。
- 不支持并发写入,文件随机修改:一个文件只能有一个写,不允许多个线程同时写;仅支持append(追加),不支持文件的随机修改。
- 优点:
- 组成
- NemeNode(nn):就是Matser,它是一个主管、管理者
- DataNode:就是Slave。NameNode下达命令DataNode执行实际的操作。
- Client:就是客户端
- SecondaryNameNode:并非NameNode的热备。党NameNode挂掉的时候,它并不能马上替换NamNode并提供服务。
- 文件块的大小
- HDFS中的文件在物理上分块存储(Block),块的大小可以通过参数配置来规定的,默认在Hadoop2x/3x版本中是128M,1x版本中是64M
- 寻址时间为传输时间的1%时,则为最佳状态。因此,传输时间=10ms/0.01=1000ms
- 总结:HDFS块的大小取决于磁盘的传输速率。
二、HDFS的Shell相关操作(开发重点)
- 基本语法:hadoop fs 具体命令 或者 hdfs dfs 具体命令(两个完全相同)
- 基本命令:准备工作:必须启动集群(sbin/start-dfs.sh和sbin/start-yarn.sh)
- hadooop fs -help 命令 输出这个命令的参数
- hadoop fs -mkdir 文件夹名称 创建文件夹
- (上传)hadoop fs -moveFromLocal 源路径 上传的路径 上传文件夹到hdfs,剪切的方式。
- (上传)hadoop fs -copyFromLocal 源路径 上传的路径 上传文件到hdfs,复制的方式。
- (追加)hadoop fs -appendToFile 要追加的文件路径 被追加的文件路径 在一个文件里的内容后追加新的内同。
- (下载)hadoop fs -get 源文件的路径 目标路径 从hdfs下载
- HDFS直接操作
- (-ls)hadoop fs -ls 文件夹路径 显示目录信息
- (-cat) hadoop fs -cat 文件的路径 查看文件内容
- (-chgrp、chmod、chown)hadoop fs -chmod 666 修改文件权限 hadoop fs -chown nancheng:nancheng 文件路径 修改所属用户
- (makdir)hadoop fs -makdir 新的文件夹路径 创建目录
- (-cp)hadoop fs -cp 原始路径 目标路径 从HDFS的一个路径拷贝到另一个路径
- (-mv)hadoop fs -mv 源文件路径 目标路径 移动文件
- (-tail) hadoop fs -tail 源文件路径 显示一个文件末尾1kb的数据
- (-rm)hadoop fs -rm 源文件路径 删除文件夹或文件
- (-rm -r)hadoop fs -rm -r 源文件路径 递归删除文件夹
- (-du)hadoop fs -du -s -h 源文件路径 统计文件夹的大小信息
- (-setrep)hadoop fs -setrep 源文件夹路径 更改副本数量
三、HDFS的客户端API(数据的上传和下载)
- 配置Hadoop环境变量
- 配置maven环境
- 在软件商店下载idea(在插件里搜索中文可以下载中文插件)
- 打开idea-》新建-》点maven-》下一步->点开下拉箭头
- 修改maven路径->文件->设置->
- 添加依赖
<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>
-
在项目的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
;
-
在java包下创建包名:hads(前置准备工作已经准备好了)
-
在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文件写入流程:
- 客户端向Namenode发起文件写入的请求
- Namennode根据文件大小和文件块配置情况,返回给客户端所管理部分Datanode的信息;
- 客户端将文件划分成为多个块,根据Datanode的地址信息,按顺序写入到每一个Datanode块中
(图片来自尚硅谷) 、
网络拓扑-节点距离:两个节点到达最近的共同祖先的距离总和。
机架感知(副本存储节点选择)
- 第一个副本在客户端所在处的节点上选择一个,如歌客户端在集群外,随机选 一个
- 第二个副本在另一个机架的随机一个节点
- 第三个副本在第二个副本所在的机架的随机节点
HDFS读数据流程:
- 客户端向Namenode发起文件读取的请求
- Namenode返回文件存储的Damenode的信息
- 客户端读取文件信息
HDFS读数据流程
(图片来自尚硅谷)
五、NN和2NN(了解)
数据存储在内存:好处:计算快 坏处:可靠性差 磁盘:好处:可靠性高 坏处:计算慢 内存+磁盘->效率底 fslmage 存储数据(如果是随机读写效率a=10 a+10->a=20) Edits 追加->
Namenode:HDFS的守护进程,用来管理文件系统的命名空间,负责记录文件是如何分割成数据块的,以及这些数据块分别被存储到那些数据节点上,它的主要功能是对内存及IO进行集中管理
Secondary Namenode :辅助后台程序,与Namenode进行通信,以便定期保存HDFS元数据的快照,用以备份和恢复数据。
HDFS-API-Fsimage和Edits解析
- Fsinmage文件:HDFS文件系统元数据的一个永久性的检查点,其中包含所有目录和文件的inode序列化信息。
- Edits文件:存放HDFS文件系统的所有更新操作的路径,文件系统客户端的所有写操作首先会被记录到Edits文件中。
- seen-exid文件保存的是一个数字,就是最后一个edits-的数字。
- 每次NameNode启动的时候都会将Fsimage文件读入内存,加载Edits里面的更新操作,保证内存中的元数据信息是最新的、同步的,可以看成NameNode启动的时候就将Fsimage和Edits文件进行了合并。
六、Datanode工作机制(了解底层原理)
A、工作机制
(图片来自尚硅谷)
B、Fsimage和Edits解析
一、oiv查看Fsimage文件
- 查看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
;
-
基本语法
hdfs oiv -p 文件类型 -i镜像文件 -o 转换后文件输出路径
;
-
下载到win电脑
-
在win系统中查看
二、oev查看Edits文件
基本语法
hdfs oev -p 文件类型 -i编辑日志 -o 转换后文件输出路径
C、CheckPoint时间设置
- 通常情况下:SecondaryNameNode每隔一小时执行一次
- 一分钟检查一次操作次数,当操作次数达到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、掉线时参数设置
- DataNode进程死亡或者网络故障造成DataNode无法与NameNode通信
- NameNode不会立即把该节点判断为死亡,要经过一段时间,这段时间暂称作超时时长
- HDFS默认的操作时长为10分钟+30秒
- 如果定义时间为TimeOut,则超时时长的计算公式为:TimeOut = 2*dfs.namenodleheatbeat.interval.而默认的是hdfs-site。xml配置的文件中的hearbeat.recheck.interval大小为5分钟,dfs.heartbeat.interval.
- 需要注意的是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>
;