文章目录
- 一、简介
- 1、定义
- 2、HDFS优缺点
- 3、HDFS组成架构
- 4、HDFS文件块大小
- 二、HDFS的读写流程
- 1、HDFS写数据流程
- 2、HDFS读数据流程
- 3、网络拓扑-节点距离计算
- 4、机架感知(副本存储节点选择)
- 三、NameNode和SecondaryNameNode
- 1、NN和2NN工作机制
- 2、Fsimage和Edits解析
- 3、CheckPoint时间设置
- 四、DataNode
- 1、DataNode工作机制
- 2、数据完整性
- 3、掉线时参数设置
- 五、HDFS的Shell操作
- 1、基本操作
- 2、文件上传
- 3、文件下载
- 六、HDFS的API操作
- 1、客户端环境准备
- 2、HDFS的API操作
- 2.1 获取链接
- 2.2 上传文件
- 2.3 下载文件
- 3、参数配置
- 3.1 代码配置
- 3.2 配置文件配置
一、简介
1、定义
随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切需要一种系统来管理多台机器上的文件,这就是分布式文件管理系统。HDFS只是分布式文件管理系统中的一种。
HDFS(Hadoop Distributed File System)
,它是一个文件系统,用于存储文件,通过目录树来定位文件;其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器有各自的角色。
HDFS的使用场景:适合一次写入,多次读出的场景。一个文件经过创建、写入和关闭之后就不需要改变。
2、HDFS优缺点
- 缺点:
- 不适合低延时数据访问,比如毫秒级的存储数据,是做不到的。
- 2)无法高效的对大量小文件进行存储。
- 存储大量小文件的话,它会占用NameNode大量的内存来存储文件目录和块信息。这样是不可取的,因为NameNode的内存总是有限的;
- 小文件存储的寻址时间会超过读取时间,它违反了HDFS的设计目标。
- 不支持并发写入、文件随机修改。
- 一个文件只能有一个写,不允许多个线程同时写;
- 仅支持数据append(追加),不支持文件的随机修改。
3、HDFS组成架构
NameNode(nn)
:就是Master,它是一个主管、管理者。
(1)管理HDFS的名称空间;
(2)配置副本策略;
(3)管理数据块(Block)映射信息;
(4)处理客户端读写请求。
- 2)
DataNode
:就是Slave。NameNode下达命令,DataNode执行实际的操作。
(1)存储实际的数据块;
(2)执行数据块的读/写操作。
- 3)
Client
:就是客户端。
(1)文件切分。文件上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行上传;
(2)与NameNode交互,获取文件的位置信息;
(3)与DataNode交互,读取或者写入数据;
(4)Client提供一些命令来管理HDFS,比如NameNode格式化;
(5)Client可以通过一些命令来访问HDFS,比如对HDFS增删查改操作;
- 4)
Secondary NameNode
:并非NameNode的热备。当NameNode挂掉的时候,它并不能马上替换NameNode并提供服务。
(1)辅助NameNode,分担其工作量,比如定期合并Fsimage和Edits,并推送给NameNode ;
(2)在紧急情况下,可辅助恢复NameNode。
4、HDFS文件块大小
- 为什么块的大小不能设置太小,也不能设置太大?
(1)HDFS的块设置太小,会增加寻址时间,程序一直在找块的开始位置;
(2)如果块设置的太大,从磁盘传输数据的时间会明显大于定位这个块开始位置所需的时间。导致程序在处理这块数据时,会非常慢。
总结:HDFS块的大小设置主要取决于磁盘传输速率。
二、HDFS的读写流程
1、HDFS写数据流程
- 客户端通过Distributed FileSystem模块向NameNode请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在。
- NameNode返回是否可以上传。
- 客户端请求第一个 Block上传到哪几个DataNode服务器上。
- NameNode返回3个DataNode节点,分别为dn1、dn2、dn3。
- 客户端通过FSDataOutputStream模块请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成。
- dn1、dn2、dn3逐级应答客户端。
- 客户端开始往dn1上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以Packet为单位,dn1收到一个Packet就会传给dn2,dn2传给dn3;dn1每传一个packet会放入一个应答队列等待应答。
- 当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器。(重复执行3-7步)。
2、HDFS读数据流程
- 1)客户端通过DistributedFileSystem向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址。
- 2)挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据。
- 3)DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)。
- 4)客户端以Packet为单位接收,先在本地缓存,然后写入目标文件。
3、网络拓扑-节点距离计算
- 在HDFS写数据的过程中,NameNode会选择距离待上传数据最近距离的DataNode接收数据。
- 节点距离:两个节点到达最近的共同祖先的距离总和。
4、机架感知(副本存储节点选择)
官方文档:http://hadoop.apache.org/docs/r3.1.3/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html
源码说明:Crtl + n 查找BlockPlacementPolicyDefault
,在该类中查找chooseTargetInOrder
方法。
三、NameNode和SecondaryNameNode
1、NN和2NN工作机制
FsImage:产生在磁盘中备份元数据的文件。
Edits:只进行追加操作,效率很高。每当元数据有更新或者添加元数据时,修改内存中的元数据并追加到Edits中。
如果长时间添加数据到Edits中,会导致该文件数据过大,效率降低,而且一旦断电,恢复元数据需要的时间过长。因此,需要定期进行FsImage和Edits的合并,如果这个操作由NameNode节点完成,又会效率过低。因此,引入一个新的节点SecondaryNamenode
,专门用于FsImage和Edits的合并。
- NameNode启动
(1)第一次启动NameNode格式化后,创建Fsimage和Edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存。
(2)客户端对元数据进行增删改的请求。
(3)NameNode记录操作日志,更新滚动日志。
(4)NameNode在内存中对元数据进行增删改。
- 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。
2、Fsimage和Edits解析
NameNode被格式化之后,将在/opt/module/hadoop-3.1.3/data/tmp/dfs/name/current目录中产生如下文件:
fsimage_0000000000000000000
fsimage_0000000000000000000.md5
seen_txid
VERSION
- Fsimage文件:HDFS文件系统元数据的一个永久性的检查点,其中包含HDFS文件系统的所有目录和文件inode的序列化信息。
- Edits文件:存放HDFS文件系统的所有更新操作的路径,文件系统客户端执行的所有写操作首先会被记录到Edits文件中。
- seen_txid文件保存的是一个数字,就是最后一个edits_的数字。
- 每次NameNode启动的时候都会将Fsimage文件读入内存,加载Edits里面的更新操作,保证内存中的元数据信息是最新的、同步的,可以看成NameNode启动的时候就将Fsimage和Edits文件进行了合并。
oiv查看Fsimage文件
fsimage
文件位置
cd /opt/module/hadoop-3.1.3/data/dfs/name/current/
解析fsimage,生成XML文件
# 语法
hdfs oiv -p 文件类型 -i镜像文件 -o 转换后文件输出路径
hdfs oiv -p XML -i fsimage_0000000000000000025 -o /opt/module/hadoop-3.1.3/fsimage.xml
文件部分内容
<inode><id>16386</id><type>DIRECTORY</type><name>user</name><mtime>1512722284477</mtime><permission>atguigu:supergroup:rwxr-xr-x</permission><nsquota>-1</nsquota><dsquota>-1</dsquota>
</inode>
<inode><id>16387</id><type>DIRECTORY</type><name>atguigu</name><mtime>1512790549080</mtime><permission>atguigu:supergroup:rwxr-xr-x</permission><nsquota>-1</nsquota><dsquota>-1</dsquota>
</inode>
<inode><id>16389</id><type>FILE</type><name>wc.input</name><replication>3</replication><mtime>1512722322219</mtime><atime>1512722321610</atime><perferredBlockSize>134217728</perferredBlockSize><permission>atguigu:supergroup:rw-r--r--</permission><blocks><block><id>1073741825</id><genstamp>1001</genstamp><numBytes>59</numBytes></block></blocks>
</inode >
oev查看Edits文件
cd /opt/module/hadoop-3.1.3/data/dfs/name/current/
# 基本语法
hdfs oev -p 文件类型 -i编辑日志 -o 转换后文件输出路径
hdfs oev -p XML -i edits_0000000000000000363-0000000000000000363 -o /opt/module/hadoop-3.1.3/edits.xml
3、CheckPoint时间设置
配置文件:hdfs-default.xml
- 通常情况下,SecondaryNameNode每隔一小时执行一次。
<!-- 单位:秒 -->
<property><name>dfs.namenode.checkpoint.period</name><value>3600</value>
</property>
- 一分钟检查一次操作次数,当操作次数达到1百万时,SecondaryNameNode执行一次。
<property><name>dfs.namenode.checkpoint.txns</name><value>1000000</value>
<description>操作动作次数</description>
</property><property><name>dfs.namenode.checkpoint.check.period</name><value>60</value>
<description> 1分钟检查一次操作次数</description>
</property>
四、DataNode
1、DataNode工作机制
- 一个数据块在DataNode上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。
- DataNode启动后向NameNode注册,通过后,周期性(6小时)的向NameNode上报所有的块信息。
- 心跳是每3秒一次,心跳返回结果带有NameNode给该DataNode的命令如复制块数据到另一台机器,或删除某个数据块。如果超过10分钟+30秒没有收到某个DataNode的心跳,则认为该节点不可用。
- 集群运行中可以安全加入和退出一些机器。
DN向NN汇报当前解读信息的时间间隔,默认6小时
<property><name>dfs.blockreport.intervalMsec</name><value>21600000</value><description>Determines block reporting interval in milliseconds.</description>
</property>
DN扫描自己节点块信息列表的时间,默认6小时
<!-- 单位:秒 -->
<property><name>dfs.datanode.directoryscan.interval</name><value>21600</value><description>Interval in seconds for Datanode to scan data directories and reconcile the difference between blocks in memory and on the disk.Support multiple time unit suffix(case insensitive), as describedin dfs.heartbeat.interval.</description>
</property>
2、数据完整性
DataNode节点保证数据完整性的方法。
- (1)当DataNode读取Block的时候,它会计算CheckSum。
- (2)如果计算后的CheckSum,与Block创建时值不一样,说明Block已经损坏。
- (3)Client读取其他DataNode上的Block。
- (4)常见的校验算法crc(32),md5(128),sha1(160)。
- (5)DataNode在其文件创建后周期验证CheckSum。
3、掉线时参数设置
hdfs-site.xml
:配置文件中的heartbeat.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>
五、HDFS的Shell操作
1、基本操作
fs
:查看所有命令
hadoop fs
-help
:查看rm帮助内容
hadoop fs -help rm
-ls
: 显示目录信息
hadoop fs -ls /test01
-cat
:显示文件内容
hadoop fs -cat /test01/test01.txt
-chgrp
、-chmod
、-chown
:Linux文件系统中的用法一样,修改文件所属权限
hadoop fs -chmod 777 /test01/test01.txt
hadoop fs -chown lydms:lydms /test01/test01.txt
-mkdir
:创建路径
hadoop fs -mkdir /test02
-cp
:从HDFS的一个路径拷贝到HDFS的另一个路径
hadoop fs -cp /test01/test01.txt /test02
-mv
:在HDFS目录中移动文件
hadoop fs -mv /test01/test.txt /test02
-tail
:显示一个文件的末尾1kb的数据
hadoop fs -tail /test01/test01.txt
-rm
:删除文件或文件夹
hadoop fs -rm /test01/test02.txt
-rm -r
:递归删除目录及目录里面内容
hadoop fs -rm -r -f /test02
-du
:统计文件夹的大小信息
hadoop fs -du /test01
-setrep
:设置HDFS中文件的副本数量
hadoop fs -setrep 10 /test01/test01.txt
2、文件上传
-moveFromLocal
:将本地文件test.txt
剪切到Hadoop中test01
目录下
hadoop fs -moveFromLocal ./test.txt /test01
-copyFromLocal
:将本地文件test01
复制到Hadoop中test01
目录下
hadoop fs -copyFromLocal ./test01.txt /test01
-put
:等同于-copyFromLocal
。将本地文件test02
复制到Hadoop中test01
目录下
hadoop fs -put ./test02.txt /test01
-appendToFile
:追加一个文件到已经存在的文件末尾
hadoop fs -appendToFile ./test03.txt /test1/test01.txt
3、文件下载
-copyToLocal
:从HDFS拷贝到本地
hadoop fs -copyToLocal /test01/test01.txt /home/lydms/
-get
:等同于copyToLocal,生产环境更习惯用get
hadoop fs -get /test01/test02.txt ./
六、HDFS的API操作
1、客户端环境准备
下载软件到本地
wget https://gitcode.net/weixin_44624117/software/-/blob/master/software/Linux/Hadoop/hadoop-3.1.3.tar.gz
添加环境变量:
vim /etc/profile
# 添加内容
#HADOOP_HOME
export HADOOP_HOME=/Users/liyangda/file/linux/hadoop-3.1.3
export PATH=$PATH:$HADOOP_HOME/bin
执行检测
source /etc/profile
# 查看是否添加成功
hadoop
2、HDFS的API操作
2.1 获取链接
- 方式一:
/*** 创建连接:方式一*/
@Test
public void getConn01() throws IOException, InterruptedException, URISyntaxException {// 1 获取文件系统Configuration configuration = new Configuration();// 配置在集群上运行FileSystem fs = FileSystem.get(new URI("hdfs://hadoop101:8020"),configuration,"lydms");
}
- 方式二(没用过):
/*** 创建连接:方式二*/
@Test
public void getConn02() throws IOException, InterruptedException, URISyntaxException {// 1 获取文件系统Configuration configuration = new Configuration();// 配置在集群上运行configuration.set("fs.defaultFS", "hdfs://hadoop101:8020");FileSystem fs = FileSystem.get(configuration);
}
运行时需要配置用户名称(默认是使用windows用户名操作HDFS)
客户端去操作HDFS时,是有一个用户身份的。默认情况下,HDFS客户端API会从JVM中获取一个参数来作为自己的用户身份:-DHADOOP_USER_NAME=lydms
,
2.2 上传文件
/*** 上传文件*/
@Test
public void testCopyFromLocalFile() throws IOException, InterruptedException, URISyntaxException {// 1 获取文件系统Configuration configuration = new Configuration();FileSystem fs = FileSystem.get(new URI("hdfs://hadoop101:8020"), configuration, "lydms");// 2 上传文件fs.copyFromLocalFile(new Path("/Users/liyangda/Code/DemoProject/first-scala/src/main/resources/test03.txt"), new Path("/test01"));// 3 关闭资源fs.close();
}
2.3 下载文件
/*** 下载文件*/
@Test
public void testCopyToLocalFile() throws IOException, InterruptedException, URISyntaxException {// 1 获取文件系统Configuration configuration = new Configuration();FileSystem fs = FileSystem.get(new URI("hdfs://hadoop101:8020"), configuration, "lydms");// 2 执行下载操作// boolean delSrc 指是否将原文件删除// Path src 指要下载的文件路径// Path dst 指将文件下载到的路径// boolean useRawLocalFileSystem 是否开启文件校验fs.copyToLocalFile(false, new Path("/test01/test01.txt"), new Path("/Users/liyangda/Code/DemoProject/first-scala/src/main/resources"), true);// 3 关闭资源fs.close();
}
3、参数配置
3.1 代码配置
@Test
public void test01() throws IOException, InterruptedException, URISyntaxException {// 1 获取文件系统Configuration configuration = new Configuration();// 配置副本数configuration.set("dfs.replication", "2");FileSystem fs = FileSystem.get(new URI("hdfs://hadoop101:8020"), configuration, "lydms");// 2 上传文件fs.copyFromLocalFile(new Path("src/main/resources/test05.txt"), new Path("/test01"));// 3 关闭资源fs.close();
}
3.2 配置文件配置
配置文件:Resource
目录下hdfs-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?><configuration><property><name>dfs.replication</name><value>10</value></property>
</configuration>
代码
@Test
public void test01() throws IOException, InterruptedException, URISyntaxException {// 1 获取文件系统Configuration configuration = new Configuration();FileSystem fs = FileSystem.get(new URI("hdfs://hadoop101:8020"), configuration, "lydms");// 2 上传文件fs.copyFromLocalFile(new Path("src/main/resources/test05.txt"), new Path("/test01"));// 3 关闭资源fs.close();
}
结果