大数据平台技术课程实验报告实验二HDFS操作实践
大数据平台技术课程实验报告实验二:HDFS操作实践
实验内容与要求:
HDFS基本知识总结
2 HDFS接口的操作实践
2.1 HDFS Shell 实践
2.2 HDFS Web客户端
2.3 HDFS Java API 实践
H DFS基本知识的总结
HDFS分布式文件系统:
单台计算机的存储无法满足大数据时代下的海量信息。分布式文件系统为人们提供了一种解决大数据存储的方案。分布式文件系统在单台计算节点文件系统之上,利用网络将大量计算节点互联,向下将各个节点中的存储容量进行集中管理,向上为用户提供透明化服务,使得人们在使用分布式文件系统时就像使用本地文件系统一样,无须关心数据是存储在哪个节点上或者从哪个节点上获取的。
HDFS的设计目标:
- 硬件故障容错:数据在HDFS中会自动保存多个副本。在因机器故障而导致某一个副本丢失以后,HDFS副本冗余机制会自动复制其他机器上的副本,保障数据的可靠性。
- 流式数据访问:HDFS采用的数据访问模式是一次写入,多次读取。HDFS适合批量处理
- 面向大数据集:HDFS支持大文件处理不支持小文件处理
- 简化的一致性模型:HDFS采取的是一次写入,多次读取的数据访问模式
- 移动计算程序比移动数据更经济:HDFS提供了接口来让计算程序代码移动到靠近数据存储的位置
- 跨异构软硬件平台的可移植性:基于Java语言进行开发,HDFS被设计成为易于从一个平台移植到另一个平台。
HDFS的原理与架构:
(1)HDFS的数据块:HDFS 将大文件按照固定大小拆分成一个个数据块,然后将数据块发送到集群的不同节点进行存储。 HDFS 在将大文件分成各个数据块的时候,并不关心文件里边的内容,而是根据内容在文件的偏移量(相对于文件头的偏移)来进行分割。 对于文本文件而言,为了保证在处理时数据的完整性, HDFS 在读取到一个数据块之后,判断如果当前的一个数据块不是文件起始的数据块,则会将当前块的第一行内容丢弃,但会多读取一行,以保证块末尾被分割内容的完整性。
如果将数据块的大小设置为一个较小的数值,将导致一个大文件被分割为大量的数据块。因此, HDFS 将块的大小设置为一个较大的值是为了减少查找的时间,减少定位文件与传输文件所用的时间。
(2)HDFS的架构: 一个集群中包含一个 NameNode 节点、一个 Secondary NameNode 节点。 Secondary Name - Node 为主 NameNode 节点提供备份。 Data节点运行 DataNode 进程,是 HDFS 的数据存储节点 并且要负责用户对数据的读取请求,一个集群会有多个 DataNode 节点。
当一个 DataNode 启动时,帮助 NameNode 建立各个数据块到 DataNode 的映射关系。 NameNode 也会随着 DataNode 的心跳返回一些指令给 DataNode 。
(3)数据块大多副本存储策略:HDES 在设计时提供了数据块的多副本存储策略,也就是 HDFS 为每个 数据块在集群中提供多个备份。 HDFS 采取的是同节点和同机架并行、三副本存储的默认模式。也就是说,在默认情况下,每个数据块在集群中有3个副本,第一个副本存储在用户所使用的机器节点上,第二个副本存放在集群中第一个副本不同机架的机器节点上,第三个副本存放在与第二个副本同一个机架的不同机器节点上。
HDFS的操作流程
(1)HDFS文件读流程
该操作流 中主要涉及 NameNode 节点、 DataNode 节点和 Client Node 节点。其中, Client Node 节点就是 HDES 集群中用户使用 HDFS 客户端( HDFS 的 Shell 客户端或者 Java API 客户端)来操作 HDFS 的节点。
首先,客户端使用 FileSystem 的 open ()操作打开一个指定路径的文件。 的 open ()操作返回一个 FSDatalnputStream 输人流对象。在获得输人流对象 DEFSDatalnputStream 之后,客户端调用该对象的 read ()操作来读取数据。输入流对象将选择离客户端最近的 建立连接并读取数据。 在读取数据 过程中,每读取完一个块就会进行验证,如果读取时出现错误,客户端就会通知 NameNode ,并从下一个拥有该块的 Data - Node 继续读取,失败的数据节点将被记录,以后不再连接。当一个数据块读取完毕时, DFSDatalnputStream 对象关闭与数据块所在节点的连接,然后再次通过 getBlockLocations ()方法获取下一个数据块的位置,并连接该数据块所在的离客户端最近的 DataNode 节点来读取数据……依此进行。
(2)HDFS文件写流程
首先客户端会通过FileSystem在 HDFS 中的具体实现 DistributedFileSystem 的 create ()操作来创建文件。该操作将返回一个 FSDataOutpulStream 输出流对象。在获得 FSDataOutpulStream 对象之后,客户端将会通过该对象的 write ()操作向 HDES 写人数据。该对象将需要写入的数据进行分块,然后写入对象的内部队列。 FSDataQutput Stream 对象向 NameNode 节点申请保存该文件及其副本的 DataNode 节点,分配的 DataNode 节点将放在一个数据流管道 pipeline 里。 ESDataOutputStream 对象将数据块写人 pipeline 中的第一个数据节点,然后第一个 DataNode (第一副本)节点将数据块发送给第二个 DataNode (第二副本)节点,第二个 DataNode (第二副本)节点将数据发送给第三个 DataNede (第三副本)节点,此过程即完成数据块多副本的复制
- HDFS的操作实践
2 .1 H DFS Shell 实践
(1)列举一个目录的所有文件
命令 格式 如下 :
hadoop fs -ls 目录的路径
hadoop fs -ls /
(2) 创建一个文件夹
命令 格式 如下 :
hadoop fs -mkdir 目录的路径
hadoop fs -mkdir /dataset
hadoop fs -ls /
(3) 将本地文件上传至HDFS
命令 格式 如下 :
hadoop fs -put 本地文件路径/目标路径
cd /home/zylj
vim example.txt
hadoop fs -put /home/zylj/example.txt /dataset
hadoop fs -ls /dataset
(4)将文件从HDFS下载到文件系统
命令格式如下:
hadoop fs -get HDFS 文件路径 本地存放路径
hadoop fs -get /dataset/example.txt /home/zylj/123
cd /home/zylj/123
ls
- 查看文件的内容
命令格式如下:
hadoop fs -text(cat) HDFS文件的路径
hadoop fs -text /dataset/example.txt
- 删除文件或者文件夹
命令格式如下:
Hadoop fs -rm(rmr) HDFS中文件或者文件夹的路径
hadoop fs -rm /dataset/example.txt
2.2 HDFS Web客户端
在终端打开HDFS后,打开虚拟机输入http://localhost:50070
- H DFS Java API 实践
- 在pom.xml文件中配置Jar依赖包
- 在Maven项目中创建一个Java类实现相关功能
全套代码如下所示:
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileUtil;
import java.net.URI;
public class HDFSapp {
String hdfsURL = "hdfs://localhost:9000";
FileSystem fs = null;
Configuration configuration = null;
public HDFSapp() {
try {
configuration = new Configuration();
fs = FileSystem.get(URI.create(hdfsURL), configuration);
} catch(Exception e) {
System.out.println("An exception occurred: " + e.getMessage());
}
}
public static void main(String[] args) {
HDFSapp hdfsclient = new HDFSapp();
hdfsclient.mkdir();
hdfsclient.create();
hdfsclient.put();
hdfsclient.get();
hdfsclient.delete();
}
public void mkdir() {
try {
boolean made = fs.mkdirs(new Path("/dataset/test"));
if (made) {
System.out.println("A directory is created!");
} else {
System.out.println("Failed to create directory.");
}
} catch(Exception e) {
System.out.println("An exception occurred: " + e.getMessage());
}
}
public void create() {
try {
Path filePath = new Path("/dataset/testfile.txt");
FSDataOutputStream outputStream = fs.create(filePath);
outputStream.close();
System.out.println("File created successfully: " + filePath);
} catch (Exception e) {
System.out.println("An exception occurred: " + e.getMessage());
}
}
public void put() {
try {
Path localFilePath = new Path("/path/to/local/file.txt"); // 替换为本地文件路径
Path hdfsFilePath = new Path("/dataset/hdfsfile.txt"); // 替换为HDFS目标路径
FileUtil.copy(localFilePath, fs, hdfsFilePath, false, configuration);
System.out.println("File uploaded successfully from " + localFilePath + " to " + hdfsFilePath);
} catch (Exception e) {
System.out.println("An exception occurred: " + e.getMessage());
}
}
public void get() {
try {
Path hdfsFilePath = new Path("/dataset/hdfsfile.txt"); // 替换为HDFS文件路径
Path localFilePath = new Path("/path/to/local/file.txt"); // 替换为本地目标路径
FileUtil.copy(fs, hdfsFilePath, new Path(localFilePath), false, configuration);
System.out.println("File downloaded successfully from " + hdfsFilePath + " to " + localFilePath);
} catch (Exception e) {
System.out.println("An exception occurred: " + e.getMessage());
}
}
public void delete() {
try {
boolean deleted = fs.delete(new Path("/dataset/test"), true);
if (deleted) {
System.out.println("Directory is deleted!");
} else {
System.out.println("Failed to delete directory.");
}
} catch(Exception e) {
System.out.println("An exception occurred: " + e.getMessage());
}
}
}