Hadoop3.x组件HDFS入门
一、HDFS是什么?
HDFS,全称Hadoop Distributed File System,即Hadoop分布式文件存储系统,是Hadoop核心组件之一,是大数据生态最底层的分布式存储服务。HDFS主要为了解决大数据如何存储的问题,是一种能够在普通硬件上运行的分布式文件系统。HDFS它本身是高度容错的,使用多台计算机来存储文件,并提供统一的访问接口,使得访问HDFS就像是访问一个普通文件系统一样便捷。
二、为什么需要HDFS?
在没有大数据技术以前,通常解决单机存储容量问题我们都是不断地加磁盘,但是这种方式很粗暴很原始,无法保证存储数据的高效读写和可靠性。所以后来有了RAID方案,即独立磁盘冗余阵列:
- 增加磁盘来提高存储容量上限;
- 对数据进行冗余存储来保证数据的可靠性;
- 并行读写来保证数据读写的高效率;
但是,RAID是从垂直伸缩的角度来解决单机大数据存储问题的,可扩展性终究有尽头,且成本会直线提高,因此现在已经很少被使用了。后来才有了分布式文件存储系统(DFS),其是从水平伸缩的角度来解决存储问题的,其可扩展性理论上没有上限:
- 增加普通机器来提高存储量上限;
- 将数据冗余多份存储在多台机器上来保证数据的可靠性;
- 多台机器并行读写来保证数据读写的高效率;
DFS通常采用树形目录的抽象逻辑来代替硬盘等物理设备的概念,用户不用关心数据底层存放在哪台机器哪块磁盘上,只需要记住数据存放的目录和文件名即可。
2003年Google发表了GFS的论文,而HDFS则是根据这篇论文实现的DFS,是目前大数据生态主流的底层分布式文件系统。
HDFS在大数据生态中的地位HDFS的设计目标为:
- 一次写入多次读取,特别适用于一旦将数据导入之后不需要修改的场景,放弃了对数据一致性的追求从而使得高吞吐量的数据访问成为可能;
- 大数据场景下移动计算要比移动数据来的划算,将计算程序分发到数据所在的地方进行计算,大大提高了任务的完成时效性;
- HDFS可以很方便地在不同平台之间移植,确保其受欢迎的程度。
所以,如果是大数据量、一次写入多次读取、高容错的计算场景,就非常适合使用HDFS。
三、HDFS是如何工作的?
HDFS主要分为角色:
- NameNode,是HDFS集群的主节点,用来记录文件的元数据,比如文件的名称、权限、修改时间、大小、数据块大小、以及文件被存放在哪些DataNode上的信息,是整个HDFS集群的唯一入口;
- DataNode,是HDFS集群的从节点,用来存储数据块,DataNode的多少决定了HDFS集群的存储能大小,主要负责将自己注册到NameNode上,并持续汇报自己持有的块列表信息;
- SecondaryNameNode,NameNode的辅助节点,帮助主节点进行元数据的合并等工作;
- SidebyNameNode,NameNode的备份节点,实时同步备份NameNode上的所有数据,当NameNode故障时,SidebyNameNode能立即成为新的NameNode,保证HDFS集群能持续工作,通过Zookeeper确保一个集群中任意时刻只能有一个NameNode。
HDFS主要拥有如下的特性:
-
主从架构,NameNode为主,DataNode为从;
-
分块存储,文件在物理上是被分块存储在不同的DataNode上的,默认的块大小为128M,超过该大小就会被分块,不足该大小就自成一块;
-
副本机制,所有的文件块都是有副本的,默认每个数据块有3份,确保高容错性;
-
元数据记录,NameNode记录所有的元数据,客户端通过NameNode的元数据来得知自己需要访问的数据块在哪些DataNode上;
-
抽象目录树,为用户提供了抽象的目录树结构,可以通过路径文件名的形式来访问文件,无需关心底层数据块的存储;
HDFS分块存储示意图
当HDFS集群需要写数据的时候:
- HDFS客户端创建对象实例DistributedFileSystem,该对象里面封装了和HDFS集群的一些操作方法;
- DistributedFileSystem对象通过create方法,以RPC调用的方式请求NameNode创建文件,在此过程中,NameNode会执行各种检查判断工作,比如目标文件是否已存在?父目录是否已存在?客户端是否具有该权限?只有检查通过,NameNode才会记录,并返回FSDataOutStream输出流对象给到客户端用于后续的写操作;
- HDFS客户端再将文件给到FSDataOutStream,FSDataOutStream将数据分块并写入data_queue,然后内部组件DataStream会读取该数据块,并询问NameNode该数据块应该放在哪些DataNode上;
- 当收到DataNode pipeline时,DataStream会将数据块写入pipeine中的第一个DataNode,然后由第一个DataNode再传给第二个DataNode,第二个DataNode再传给第三个DataNode;
- DataNode之间通过ack来确认自己的下一个节点已经成功收到数据,FSDataOutStream在收到ack反馈后,就能确认数据块写入集群成功;
- 客户端在写完所有数据块后调用close关闭流操作;
- 客户端通知NameNode完成过了本次文件写操作;
当HDFS集群需要读数据的时候:
- HDFS客户端创建对象实例DistributedFileSystem,该对象里面封装了和HDFS集群的一些操作方法;
- DistributedFileSystem以RPC调用的方式请求NameNode来获取前几个数据块的信息(分批读取),NameNode会返回每个块所有DataNode的列表,并且根据客户端的网络拓补距离将DataNode排好序;
- HDFS客户端将读取请求提交给FSDataInputStream输入流;
- FSDataInputStream找到数据块对应的DataNode列表中的第一个进行数据的读取;
- FSDataInputStream对每一个数据块重复上述读取操作,同时客户端也在重复上述步骤不断从NameNode获取后续批次的块信息;
- 当客户端完成读取后,就会调用close方法关闭流。
四、如何使用HDFS?
首先需要搭建一个HDFS集群,这部分内容我们原先已经完成了,可以参考:Hadoop3.x集群安装教程 - 简书 (jianshu.com)
然后我们可以通过以下两种方式来进行HDFS上的文件操作:
-
HDFS Shell CLI,通过命令行的方式来操作HDFS上的文件;支持操作多种文件系统,比如:
-
hadoop fs -ls file:///
,表示操作客户端所在本地的文件系统; -
hadoop fs -ls hdfs://10.96.182.11:8020/
,表示操作HDFS文件系统; -
hadoop fs -ls /
,不写URL协议前缀的,将会操作配置文件中fs.defaultFS
属性所代表的文件系统;这个属性在Hadoop集群的配置文件core-site.xml
中配置了:<!-- 设置默认使用的文件系统 Hadoop支持file、HDFS、GFS、ali|Amazon云等文件系统 --> <property> <name>fs.defaultFS</name> <value>hdfs://172.24.38.209:8020</value> </property>
具体的命令和Linux的差别不大,可以通过
hadoop fs -help
查看每个命令的使用帮助信息,也可以在官网查询到:Apache Hadoop 3.3.4 – Overview -
-
web UI界面,访问HDFS集群NameNode的地址即可使用,比较简单,此处省略。
在企业实际的大数据开发分析场景中,我们很少会直接操作HDFS,它太底层了,我们一般都会通过数据导入导出工具来替我们和HDFS操作,但是了解HDFS工作原理和特性还是非常有必要的,毕竟它是大数据生态的基石。