随着数据量愈来愈大,在一个操做系统存不下全部的数据,那么就分配到更多的操做系统管理的磁盘中,可是不方便管理和维护,迫切须要一种系统来管理多台机器上的文件,这就是分布式文件管理系统。HDFS只是分布式文件管理系统中的一种。java
HDFS(Hadoop Distributed File System),它是一个文件系统,用于存储文件,经过目录树来定位文件;其次,它是分布式的,由不少服务器联合起来实现其功能,集群中的服务器有各自的角色。node
HDFS的使用场景:适合一次写入,屡次读出的场景,且不支持文件的修改。适合用来作数据分析,并不适合用来作网盘应用。apache
优势:缓存
缺点:安全
HDFS 中的文件在物理上是分块存储(Block),块的大小能够经过配置参数(dfs.blocksize)来规定,默认大小在Hadoop2.x 版本中是 128M,老版本中是 64M。服务器
若是寻址时间为 100ms,即查找目标 Block 的时间是 100ms。网络
寻址时间与传输时间的比例为 100 : 1为最佳状态,所以传输时间为 1ms。架构
目前磁盘的传输速率大概在 100MB/s,取个整大概就是 128MB。并发
(1)-help:输出这个命令参数app
(2)-ls:显示目录信息
(3)-mkdir:在 HDFS 上建立目录
(4)-moveFromLocal:从本地剪切粘贴到 HDFS
(5)-appendToFile:追加一个文件到已经存在的文件末尾
(6)-cat:显示文件内容
(7)-chgrp 、-chmod、-chown:Linux 文件系统中的用法同样,修改文件所属权限
(8)-copyFromLocal:从本地文件系统中拷贝文件到 HDFS 路径去
(9)-copyToLocal:从 HDFS 拷贝到本地
(10)-cp :从 HDFS 的一个路径拷贝到 HDFS 的另外一个路径
(11)-mv:在 HDFS 目录中移动文件
(12)-get:等同于 copyToLocal,就是从 HDFS 下载文件到本地
(13)-getmerge:合并下载多个文件,好比 HDFS 的目录 /user/djm/test 下有多个文件:log.1, log.2,log.3,...
(14)-put:等同于 copyFromLocal
(15)-tail:显示一个文件的末尾
(16)-rm:删除文件或文件夹
(17)-rmdir:删除空目录
(18)-du:统计文件夹的大小信息
(19)-setrep:设置 HDFS 中文件的副本数量
package com.djm.hdfsclient; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.*; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.net.URI; public class HdfsClient { FileSystem fileSystem = null; @Before public void init() { try { fileSystem = FileSystem.get(URI.create("hdfs://hadoop102:9000"), new Configuration(), "djm"); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 上传文件 */ @Test public void put() { try { fileSystem.copyFromLocalFile(new Path("C:\\Users\\Administrator\\Desktop\\Hadoop 入门.md"), new Path("/")); } catch (IOException e) { e.printStackTrace(); } } /** * 下载文件 */ @Test public void download() { try { // useRawLocalFileSystem表示是否开启文件校验 fileSystem.copyToLocalFile(false, new Path("/Hadoop 入门.md"), new Path("C:\\Users\\Administrator\\Desktop\\Hadoop 入门1.md"), true); } catch (IOException e) { e.printStackTrace(); } } /** * 删除文件 */ @Test public void delete() { try { // recursive表示是否递归删除 fileSystem.delete(new Path("/Hadoop 入门.md"), true); } catch (IOException e) { e.printStackTrace(); } } /** * 文件重命名 */ @Test public void rename() { try { fileSystem.rename(new Path("/tmp"), new Path("/temp")); } catch (IOException e) { e.printStackTrace(); } } /** * 查看文件信息 */ @Test public void ls() { try { RemoteIterator<locatedfilestatus> listFiles = fileSystem.listFiles(new Path("/etc"), true); while (listFiles.hasNext()) { LocatedFileStatus fileStatus = listFiles.next(); if (fileStatus.isFile()) { // 仅输出文件信息 System.out.print(fileStatus.getPath().getName() + " " + fileStatus.getLen() + " " + fileStatus.getPermission() + " " + fileStatus.getGroup() + " "); // 获取文件块信息 BlockLocation[] blockLocations = fileStatus.getBlockLocations(); for (BlockLocation blockLocation : blockLocations) { // 获取节点信息 String[] hosts = blockLocation.getHosts(); for (String host : hosts) { System.out.print(host + " "); } } System.out.println(); } } } catch (IOException e) { e.printStackTrace(); } } @After public void exit() { try { fileSystem.close(); } catch (IOException e) { e.printStackTrace(); } } }
一、客户端经过 Distributed FileSystem 模块向 NameNode 请求上传文件,NameNode 检查目标文件是否已存在,父目录是否存在。
二、NameNode 返回是否能够上传。
三、客户端请求第一个 Block 上传到哪几个 DataNode。
四、NameNode 返回三个节点,分别是 dn一、dn二、dn3。
五、客户端经过 FSDataOutputStream 模块请求 dn1 上传数据,dn1 收到请求会继续调用 dn2,而后 dn2 调用 dn3,将这个通讯管道创建完成。
六、按倒序逐级响应客户端。
七、客户端开始往 dn1 上传第一个 Block(先从磁盘读取数据放到一个本地内存缓存),以 Packet 为单位,dn1 收到一个Packet 就会传给 dn2,dn2 传给 dn3;dn1 每传一个 packet 会放入一个应答队列等待应答。
八、当一个Block传输完成以后,客户端再次请求NameNode上传第二个Block的服务器。
在HDFS写数据的过程当中,NameNode会选择距离待上传数据最近距离的DataNode接收数据。那么这个最近距离怎么计算呢?
一、客户端经过 Distributed FileSystem 向 NameNode 请求下载文件,NameNode经过查询元数据,找到文件块所在的DataNode地址。
二、根据就近原则挑选一台 DataNode,请求读取数据。
三、DataNode 开始传输数据给客户端。
四、客户端以 Packet 为单位接收,先在本地缓存,而后写入目标文件。
若是存储在 NameNode 节点的磁盘中,由于常常须要进行随机访问,还有响应客户请求,必然是效率太低,所以,元数据必须存放在内存中,周所周知,内存的特色是速度快,断电后丢失数据,一旦断电,元数据丢失,整个集群就没法工做了,所以产生了用于备份元数据的 FsImage。
可是这样又会引起一个问题,当内存中的元数据更新时,FsImage 是否要同时更新,若是要同步更新,就会致使效率低,若是不一样步更新,就会致使数据一致性问题,一旦忽然断电,就会丢失一部分数据,所以,引入了 Edits(只进行追加操做,效率很高),每当元数据进行增长或者修改时,先追加到 Edits,在修改内存,这样的话,一旦断电,能够经过 FsImage 和 Edits 合成元数据。
可是,若是长时间添加数据到 Edits,致使 Edits 过大,仍是会影响效率,并且一旦断电,恢复元数据的时间也会相应增长,所以,须要按期的对 FsImage 和 Edits 进行合并,若是这个操做由 NameNode 去完成,又会效率低(由于在合并后不能处理写请求),因此引入了 SecondaryNameNode,专门用来作合并操做。
NameNode 工做:
一、第一次启动 NameNode格式化后,建立 Fsimage 和 Edits 文件,若是不是第一次启动,直接加载编辑日志和镜像文件到内存。
二、客户端对元数据进行增删改操做。
三、NameNode 记录操做日志,更新滚动日志。
四、NameNode 在内存中对元数据进行增删改操做。
Secondary NameNode 工做:
一、Secondary NameNode 询问 NameNode 是否须要 CheckPoint,直接带回 NameNode 是否检查结果。
二、Secondary NameNode请求执行CheckPoint。
三、NameNode 滚动正在写的 Edits 日志。
四、将滚动前的编辑日志和镜像文件拷贝到 Secondary NameNode。
五、Secondary NameNode 加载编辑日志和镜像文件到内存合并。
六、生成新的镜像文件 fsimage.chkpoint。
七、拷贝 fsimage.chkpoint 到 NameNode。
八、NameNode 将 fsimage.chkpoint 重命名为 fsimage。
oiv 查看Fsimage 文件
oev 查看 Edits 文件
知足如下两个条件都会触发合并操做:
一般状况下,SecondaryNameNode 每隔一小时执行一次。
[hdfs-default.xml]
<property> <name>dfs.namenode.checkpoint.period</name> <value>3600</value> </property>
一分钟检查一次操做次数,当次数到达 100 万次就会触发操做。
[hdfs-default.xml]
<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>
NameNode 故障后,能够采用以下两种方法恢复数据:
将 2NN 中的数据拷贝到 NN 存储数据的目录。
使用 -importCheckpoint 选项启动 NN 守护进程,从而将 2NN 中数据拷贝到 NN 目录中。
基本命令:
hdfs dfsadmin -safemode get:查看安全模式状态
hdfs dfsadmin -safemode enter:进入安全模式状态
hdfs dfsadmin -safemode leave:离开安全模式状态
hdfs dfsadmin -safemode wait:等待安全模式状态
一、一个数据块在 DataNode 上以文件形式存储在磁盘上,包括两个文件,一个是数据自己,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。
二、DataNode 启动后向 NameNode 注册,经过后,周期性(1小时)的向 NameNode 上报全部的块信息。
三、心跳是每 3 秒一次,心跳返回结果带有 NameNode 给该 DataNode 的命令如复制块数据到另外一台机器,或删除某个数据块,若是超过 10 分钟没有收到某个 DataNode 的心跳,则认为该节点不可用。
四、集群运行中能够安全加入和退出一些机器。
一、当 DataNode 读取 Block 的时候,它会计算 CheckSum。
二、若是计算后的 CheckSum,与 Block 建立时值不同,说明 Block 已经损坏。
三、Client 读取其余 DataNode 上的 Block。
四、在其文件建立后周期验证。
[hdfs-site.xml]
<property> <name>dfs.namenode.heartbeat.recheck-interval</name> <value>300000</value> <description>毫秒</description> </property> <property> <name>dfs.heartbeat.interval</name> <value>3</value> <description>秒</description> </property>
将 hadoop102 上的 java、hadoop、profile 发送到新主机,source 一下 profile,直接启动便可加入集群。
建立黑名单
[djm@hadoop101 hadoop]$ touch blacklist
配置加入黑名单的主机
hadoop102
配置 hdfs-site.xml
<property> <name>dfs.hosts.exclude</name> <value>/opt/module/hadoop-2.7.2/etc/hadoop/blacklist</value> </property>
刷新 namenodes
[djm@hadoop102 hadoop-2.7.2]$ hdfs dfsadmin -refreshNodes
更新 ResourceManager 节点
[djm@hadoop102 hadoop-2.7.2]$ yarn rmadmin -refreshNodes
若是数据不均衡,能够用命令实现集群的再平衡
[djm@hadoop102 hadoop-2.7.2]$ start-balancer.sh
建立白名单
[djm@hadoop101 hadoop]$ touch whitelist
配置加入黑名单的主机
hadoop102 hadoop103 hadoop104
配置 hdfs-site.xml
<property> <name>dfs.hosts</name> <value>/opt/module/hadoop-2.7.2/etc/hadoop/whitelist</value> </property>
刷新 namenodes
[djm@hadoop102 hadoop-2.7.2]$ hdfs dfsadmin -refreshNodes
更新 ResourceManager 节点
[djm@hadoop102 hadoop-2.7.2]$ yarn rmadmin -refreshNodes
若是数据不均衡,能够用命令实现集群的再平衡
[djm@hadoop102 hadoop-2.7.2]$ start-balancer.sh
黑白名单的区别:
白名单比较严格,黑名单比较平缓,处于黑名单中的主机会同步数据结束后继续处于集群,只是不在处理请求而已,而不处于白名单中的主机会直接被干掉。
DataNode也能够配置成多个目录,每一个目录存储的数据不同,即:数据不是副本。
hdfs-site.xml
<property> <name>dfs.datanode.data.dir</name> <value>file:///${hadoop.tmp.dir}/dfs/data1,file:///${hadoop.tmp.dir}/dfs/data2</value> </property>
采用 distcp 命令实现两个 Hadoop 集群之间的递归数据复制
[djm@hadoop102 hadoop-2.7.2]$ hadoop distcp hdfs://haoop102:9000/user/djm/hello.txt hdfs://hadoop103:9000/user/djm/hello.txt
归档文件
[djm@hadoop102 hadoop-2.7.2]$ hadoop archive -archiveName input.har –p /user/djm/input /user/djm/output
查看归档
[djm@hadoop102 hadoop-2.7.2]$ hadoop fs -lsr har:///user/djm/output/input.har
解归档文件
[atguigu@djm hadoop-2.7.2]$ hadoop fs -cp har:/// user/djm/output/input.har/* /user/djm
</locatedfilestatus>