一、 HDFS简介
1.1 HDFS的概述
在Hadoop生态圈中,HDFS属于底层基础,负责存储文件。
1.2 HDFS产生背景
HDFS全称为Hadoop Distributed File System,很简单Hadoop的分布式文件存储系统
**1)**HDFS 产生背景 随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系 统管理的磁盘中,但是不方便管理和维护,迫切需要一种系统来管理多台机器上的文件,这 就是分布式文件管理系统。HDFS 只是分布式文件管理系统中的一种。
**2)**HDFS 定义 HDFS,它是一个文件系统,用于存储文件,通过目 录树来定位文件;其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务 器有各自的角色。
HDFS 的使用场景:适合一次写入,多次读出的场景。一个文件经过创建、写入和关闭 之后就不需要改变。
1.3 HDFS的优点
1.高容错性。提供了容错和恢复机制,副本丢失后,自动恢复。
2.高可靠性。数据自动保存多个副本,通过多副本提高可靠性。
3.适合大数据处理。可以处理超大文件,比如 TB级甚至PB级 的文件。
4.适合批处理。移动计算而非移动数据;数据位置暴露给计算框架。
5.支持流式数据访问。一次性写入,多次读取(一个数据集一旦生成,就会被复制分发到不同的存储节点,各节点可以进行读取/访问);保证数据一致性。
6.低成本运行。可以运行在低成本的硬件之上。
HDFS 默认保存 3 份副本。
第一个副本:放置在 上传文件 的数据节点(第一个副本如果是在 集群外 提交,则随机挑选一个 CPU 比较空闲 、 磁盘不太满 的节点);
第二个副本:放置在与 第一个副本 不同 的机架的节点上;
第三个副本:放在与 第二个副本 相同 的机架的其他节点上。
1.4 HDFS的缺点
1.不适合处理 低延迟 的数据访问。比如用户 要求时间比较短 的低延迟应用(主要处理高数据吞吐量的应用)。
2.不适合处理 大量的小 文件。会造成寻址时间超过读取时间;会占用NameNode大量内存,因为3.NameNode把文件系统的元数据存放在内存中(文件系统的容量由NameNode的大小决定),小文件太多会消耗NameNode的内存。
4.不适合 并发写入。一个文件只能有一个写入者,HDFS暂不支持多个用户对同一个文件的写操作。
5.不适合 任意修改 文件。仅支持append(附加),不支持在文件的任意位置进行修改。
二、HDFS的组成节点
2.1 NameNode节点:
1):管理HDFS的命名空间
editlog(操作日志):在NameNode启动的情况下,对HDFS进行的各种操作进行记录。(HDFS客户端执行的所有操作都会被记录到editlog文件中,这些文件由edits文件保存) fsimage:包含HDFS中的元信息(比如修改时间、访问时间、数据块信息等)。
2):配置副本策略
3):管理数据块映射
4):处理客户端读写请求
2.2 DataNode节点:
1):存储实际的数据块
2):执行
3):管理数据块映射
4):处理客户端读写请求
问题:HDFS数据块默认大小为128M(Hadoop2.2之前为64M),将HDFS的数据块设置得很大的目的是什么?(传统数据块只有512个字节)
答:为了减少寻址开销,让HDFS的文件传输时间由传输速率决定(如果块设置得足够大,从磁盘 传输数据的时间 会明显大于 定位这个块开始位置 所需的时间)。
2.3 SecondaryNameNode节点:
并非NameNode的热备。当NameNode挂掉的时候,它并不 能马上替换NameNode并提供服务。
问题:一般情况下,一个集群中的SecondaryNameNode节点也是只有一个的原因是什么?
答:因为如果多的话,会增加NameNode的压力,使其忙于元数据的传输/接收、日志的传输/切换,从而导致性能下降;同时,NameNode节点也不支持做并发检查点。
1): 定期把NameNode的 fsimage 和 edits 下载到本地,再将它们加载到内存并进行合并,最后把合并后新的 fsimage 返回NameNode
2): 做备份
3): 防止edits过大
4): 在紧急情况下,可辅助恢复NameNode。
2.4 Client:就是客户端:
1): 文件切分。文件上传HDFS时,Client将文件切分成一个一个的Block,然后进行上传;
2): 与NameNode交互,获取文件的位置信息;
3): 与DataNode交互,读取或者写入数据;
4): Client提供一些命令来管理HDFS,比如NameNode格式化;
5): Client可以通过一些命令来访问HDFS,比如对HDFS增删查改操作;
三、HDFS的核心概念-Block
HDFS中的文件在物理上是分块存储(Block),块的大小可以通过配置参数 ( dfs.blocksize)来规定,默认大小在Hadoop2.x/3.x版本中是128M,1.x版本中是64M
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DDOkowBN-1635241253840)(C:\Users\86157\AppData\Local\Temp\1635231603221.png)]
问题:为什么块的大小不能设置太小,也不能设置太大?
(1)HDFS的块设置太小,会增加寻址时间,程序一直在找块的开始位置; (2)如果块设置的太大,从磁盘传输数据的时间会明显大于定位这个块开 始位置所需的时间。导致程序在处理这块数据时,会非常慢。 总结:HDFS块的大小设置主要取决于磁盘传输速率。
Block抽象的好处 block的拆分使得单个文件大小可以大于整个磁盘的容量,构成文件的Block可以分布在整个集群, 理论上,单个文件可以占据集群中所有机器的磁盘。 Block的抽象也简化了存储系统,对于Block,无需关注其权限,所有者等内容(这些内容都在文件级别上进行控制)。
Block作为容错和高可用机制中的副本单元,即以Block为单位进行复制。
四、HDFS的Shell操作
4.1 准备工作
1)启动集群方便后续的测试
[root@hadoop100 hadoop-3.1.3]# sbin/start-dfs.sh
[root@hadoop100 hadoop-3.1.3]# sbin/start-yarn.sh
2)创建/xiyou文件夹
[root@hadoop100 hadoop-3.1.3]# hadoop fs -mkdir /xiyou
在我们的web页面就看到了新建的文件夹
4.2 上传
1)-moveFromLocal:从本地剪切粘贴到 HDFS
[root@hadoop100 hadoop-3.1.3]# vi huanguoshan.txt 输入:sunwukong
[root@hadoop100 hadoop-3.1.3]# hadoop fs -moveFromLocal ./huaguoshan.txt /xiyou
2)-copyFromLocal:从本地文件系统中拷贝文件到 HDFS 路径去
[root@hadoop100 hadoop-3.1.3]# vi tianting.txt 输入:yudi
[root@hadoop100 hadoop-3.1.3]# hadoop fs -copyFromLocal tianting.txt /xiyou
文件还存在
3)-put:等同于 copyFromLocal,生产环境更习惯用 put
[root@hadoop100 hadoop-3.1.3]# vi tianting.txt 输入:yudi
[root@hadoop100 hadoop-3.1.3]# hadoop fs -put tianting.txt /xiyou
4)-appendToFile:追加一个文件到已经存在的文件末尾
[root@hadoop100 hadoop-3.1.3]# vi tianting2.txt 输入:yudi
[root@hadoop100 hadoop-3.1.3]# hadoop fs -appendToFile tianting2.txt /xiyou/tianting.txt
4.3 下载
1)-copyToLocal:从 HDFS 拷贝到本地
[root@hadoop100 hadoop-3.1.3]# hadoop fs -copyToLocal /xiyou/tianting.txt ./
2)-get:等同于 copyToLocal,生产环境更习惯用 get
[root@hadoop100 hadoop-3.1.3]# hadoop fs -get /xiyou/tianting.txt ./
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gXUAL05k-1635241253847)(C:\Users\86157\AppData\Local\Temp\1635233369997.png)]
get下载成功
4.4 HDFS直接操作
1)-ls: 显示目录信息
[root@hadoop100 hadoop-3.1.3]# hadoop fs -ls /sanguo
2)-cat:显示文件内容
[root@hadoop100 hadoop-3.1.3]# hadoop fs -cat /sanguo/shuguo.txt
3)-chgrp、-chmod、-chown:Linux 文件系统中的用法一样,修改文件所属权限
[root@hadoop100 hadoop-3.1.3]# hadoop fs -chmod 666
/sanguo/shuguo.txt
[root@hadoop100 hadoop-3.1.3]# hadoop fs -chown atguigu:atguigu
/sanguo/shuguo.txt
4)-mkdir:创建路径
[root@hadoop100 hadoop-3.1.3]# hadoop fs -mkdir /jinguo
5)-cp:从 HDFS 的一个路径拷贝到 HDFS 的另一个路径
[root@hadoop100 hadoop-3.1.3]# hadoop fs -cp /sanguo/shuguo.txt
/jinguo
6)-mv:在 HDFS 目录中移动文件
[root@hadoop100 hadoop-3.1.3]# hadoop fs -mv /sanguo/wuguo.txt /jinguo
[root@hadoop100 hadoop-3.1.3]# hadoop fs -mv /sanguo/weiguo.txt
/jinguo
7)-tail:显示一个文件的末尾 1kb 的数据
[root@hadoop100 hadoop-3.1.3]# hadoop fs -tail /jinguo/shuguo.txt
8)-rm:删除文件或文件夹
[root@hadoop100 hadoop-3.1.3]# hadoop fs -rm /sanguo/shuguo.txt
9)-rm -r:递归删除目录及目录里面内容
[root@hadoop100 hadoop-3.1.3]# hadoop fs -rm -r /sanguo
10)-du 统计文件夹的大小信息
[root@hadoop100 hadoop-3.1.3]# hadoop fs -du -s -h /jinguo
27 81 /jinguo
[root@hadoop100 hadoop-3.1.3]# hadoop fs -du -h /jinguo
14 42 /jinguo/shuguo.txt
7 21 /jinguo/weiguo.txt
6 18 /jinguo/wuguo.tx
说明:27 表示文件大小;81 表示 27*3 个副本;/jinguo 表示查看的目录
11)-setrep:设置 HDFS 中文件的副本数量
[root@hadoop100 hadoop-3.1.3]# hadoop fs -setrep 10 /jinguo/shuguo.txt
这里设置的副本数只是记录在 NameNode 的元数据中,是否真的会有这么多副本,还得
看 DataNode 的数量。因为目前只有 3 台设备,最多也就 3 个副本,只有节点数的增加到 10
台时,副本数才能达到 10。
四、HDFS的API操作
4.1 客户机准备
配置环境变量,又到了我们配置环境变量的时候了
1)将windows依赖文件,拷贝 hadoop-3.1.0 到非中文路径(比如 d:\)。
2)配置 HADOOP_HOME 环境变量
3)配置path目录
4)在IDEA中创建一个maven项目并导入要用到的包
这是我们的pom.xml配置文件文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>demo01</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>15</maven.compiler.source>
<maven.compiler.target>15</maven.compiler.target>
</properties>
<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>
</project>
4.2 创建
先来创建一个文件
@Test
public void testmkdir() throws Exception {
//连接集群nn地址
URI uri = new URI("hdfs://hadoop100:8020");
//创建一个配置
Configuration conf = new Configuration();
//获取客户端对象
fileSystem = FileSystem.get(uri, conf,"root");
//创建一个文件夹
fileSystem.mkdirs(new Path("/xiyou/shuiliandong"));
//关闭资源
fileSystem.close();
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n1nzYfvz-1635241253850)(C:\Users\86157\AppData\Local\Temp\1635234201481.png)]
测试通过来看看有没有我们需要的文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JZ05Qwtx-1635241253851)(C:\Users\86157\AppData\Local\Temp\1635234261397.png)]
有,不错
这是我们观察代码发现有很多重复性的工作,我们可以封装两个函数
FileSystem fileSystem = null;
//初始化
@Before
public void init() throws Exception{
//连接集群nn地址
URI uri = new URI("hdfs://hadoop100:8020");
//创建一个配置
Configuration conf = new Configuration();
//获取客户端对象
fileSystem = FileSystem.<