Hdfs的版本基本是对应hadooop的版本,了解hadoop的版本历程简介也就是了解HDFS的版本历程,简而言之,hadoop的大版本历程以下:node
Hadoop1.xapache
Hadoop2.x服务器
Hadoop3.x网络
其中hadoop2.x是目前大部分企业在使用的版本,hadoop1.x基本不多新项目会考虑使用这个版本,hadoop3.x是将来更多新项目会考虑使用的一个版本,这里要注意,不一样的hadoop版本存在蛮大的区别,在咱们查阅网络资料或官方文档时都要额外注意,要找到对于的版本进行学习。在没有特别版本说明的状况下,本人编写任何关于hadoop的文章都是基于hadoop3进行的。架构
理解hadoop平台
怎么去理解hadoop平台,为何一提到大数据大多数开发都知道有个hadoop平台,首先咱们来访问最新hadoop官方文档的网站:框架
https://hadoop.apache.org分布式
咱们重点关注Modules部分,能够看到,其实hadoop核心也就只有5个模块:ide
Hadoop Common: 支持其余Hadoop模块的公共应用程序工具
Hadoop Distributed File System (HDFS™): 分布式文件系统oop
Hadoop YARN: 工做调度和集群资源管理框架
Hadoop MapReduce: 基于YARN的一个计算框架
Hadoop Ozone: 对象存储框架
其实真正使用最多的只有3个:
HDFS
YARN
MAPREDUCE
为何hadoop底层只有这3个模块就能够打遍天下,号称为hadoop平台呢?缘由在于:hadoop率先提供了大数据须要的底层基础组件HDFS存储、YARN资源管理和调度、MR离线计算,后来的其它框架基本都是基于这3个进行封装的,例如hive、hbase、spark等。
HDFS架构和原理
先扔一张hadoop官方提供的HDFS的架构图:
这个图基本诠释了HDFS的总体架构和原理,理解这个图基本就理解了HDFS的原理,下面咱们就基于这个架构图来展开分析HDFS的架构和原理。
HDFS是为了解决大数据存储的一个hadoop组件,大数据的特色就是数据量大,这就有可能出现单个文件就达到TB级别,那么如今咱们思考一个问题,一个1TB的文件,如何在现有常规的服务器保存?
HDFS是这么去解决这个问题的,首先作大数据存储一台服务器确定是不够的,因此须要集群不少的服务器组成一个逻辑上的大磁盘进行存储,将任何须要存储的文件物理切割为固定大小的块,块的大小能够配置(dfs.blocksize),默认是128M(hadoop1.x默认是64M),这些块散落分布在1台或多台服务器节点上,这就解决了单个TB级别文件的存储问题。
块大小的配置颇有讲究,配置过小,会增长磁盘寻址开销,同时会增长NameNode的内存消耗,这点后面会讲到。那么问题来了,若是咱们存储都是小文件好比几十MB,那么一个块就128M,会不会存在磁盘浪费的状况呢?根据Hadoop权威指南给出的说法是这样的:
当一个1MB的文件存储在一个128MB的块中时,文件只使用1MB的磁盘空间,而不是128MB。
注意:
一、同一个文件块大小是相同的(最后一个块除外),不一样的文件块大小能够不相同。
二、文件内容只能写入一次,写入后不能修改,可是能够追加。
三、因为文件按配置块大小被物理切分,那么就存在数据完整性问题,好比hello由于单词的hel和lo分别被切分都两个块中,为了保证读取数据的完整性,mapreduce解决方式是每开始读取一个块时,都跳过第一行数据,而每一个块读取结束时,都会继续读取第二个块的第一行。
四、块在磁盘中以一个个小文件的方式进行保存。保存的目录是由块所在节点自动肯定和建立的。
HDFS集群中有两个核心角色:DataNode和NameNode,HDFS集群实际上也是一主(NameNode)多从(DataNode)的架构。DataNode角色的节点是真正存放块(block)数据的节点,当DataNode启动时,它将扫描其本地文件系统,生成与每一个本地文件相对应的全部HDFS数据块的列表,并将此报告发送到NameNode。该报告称为Blockreport。
NameNode管理文件系统的命名空间,它维护着文件系统树及整棵树内全部的文件和目录,
这些信息经过:命名空间镜像文件和编辑日志文件两种方式被永久保存在NameNode节点服务器磁盘上面。其中命名空间镜像文件保存整个文件系统的目录树,编辑日志文件记录文件系统元数据发生的全部更改。
另外NameNode内存中还保存着DataNode上报的每一个文件中各个块所在的数据节点信息,为了提高NameNode的被访问效率,同时会按期从磁盘加载命名空间到内存中保存一分内存镜像,当客户端须要读取某个文件数据时,首先访问NameNode,从NameNode内存读取文件块列表或块对应的DataNode列表,而后再访问块对应的DataNode直接从DataNode中读取数据。
若是NameNode不可用,那么等同于整个HDFS文件系统不可用,若是NameNode因为故障致使磁盘数据丢失,那么等同于整个HDFS文件系统数据丢失,若是NameNode块映射关系的内存爆满,那么等同于整个HDFS文件系统没法再继续存储,换句话说,NameNode内存决定了HDFS可以存储的块数量,根据经验值,每一个文件、目录和数据块的存储信息大约占 150 字节。
为了保证读写数据一致性,HDFS集群设计为只能有一个状态为Active的NameNode,这样就致使NameNode存在单点故障,官方提供了两种方式来解决这个问题:
QJM(推荐):经过同步编辑事务日志的方式备份命名空间数据,同时须要DataNode向全部NameNode上报块列表信息。还能够配置ZKFC组件实现故障自动转移。
NFS:将须要持久化的数据写入本地磁盘的同时写入一个远程挂载的网络文件系统作为备份。
是经过增长一个备用NameNode节点,这个备用的节点平时不工做,处于备用Standby的状态,这样就同时运行两个状态的节点,这两个节点状态分别是:Active和Standby。
咱们知道,NameNode主要保存文件系统目录树信息和块映射关系,为了保证备用节点可以随时顶替上去,因此Standby节点须要定时同步Active节点的事务日志来更新本地的文件系统目录树信息,同时DataNode须要配置全部NameNode的位置,并向全部状态的NameNode发送块列表信息和心跳。
注意,同步事务日志来更新目录树这个工做交给了一个叫JournalNode的独立守护进程来完成,简称为QJM,一个NameNode对应一个QJM进程,当Active节点执行任何命名空间文件目录树修改时,它会将修改记录持久化到大多数QJM中,Standby节点从QJM中监听并读取编辑事务日志内容,并将编辑日志应用到本身的命名空间。发生故障转移时,Standby节点将确保在将自身提高为Active状态以前,从QJM读取全部编辑内容。
注意,QJM只是实现了数据的备份,当Active节点发送故障时,须要手工提高Standby节点为Active节点。若是要实现NameNode故障自动转移,则须要配套ZKFC组件来实现,ZKFC也是独立运行的一个守护进程,基于zookeeper来实现选举和自动故障转移。
每个文件能够配置副本数量,默认是3,副本的做用是防止因某个DataNode挂掉或磁盘损坏而致使数据丢失,除此以外块副本还能够提升块可读取的节点,提升mapreduce计算任务向数据移动的几率。
由于同一个DataNode放置相同的块数据是没有意义的,因此NameNode不容许DataNode具备同一块的多个副本,换句话说副本数量配置不能大于DataNode节点的数量。
每一个文件能够在写入时指定这个文件块的副本数量,也能够在将来修改某个文件的块副本数量,文件块的副本数量配置做为块元数据的一部分保存在NameNode中。
因为NameNode能够获取每一个DataNode所属的机架ID,而且块副本数量配置信息保存在NameNode中,因此块的副本放置策略是由NameNode决定好返回给客户端的,副本放置策略简单总结一句话为:三分之一的副本位于写入器所在的节点上,三分之二的副本位于写入器所在的同一个机架上,其他三分之一则平均分布在其他机架上。若是副本数大于3个,则随机肯定其它的副本位置,通常副本数量配置为3个是比较理想的。
当修改某个文件的块副本数量时,NameNode将从新根据策略复制或减小块副本。当某个DataNode超过必定的时间(默认10分钟)没有上报心跳给NameNode,NameNode将认为该DataNode不可用,将不会分配块写入到这个DataNode中,原来分配在这个DataNode的块副本将会从新在其它可用的DataNode上复制。
虽然HDFS HA解决了“单点故障”问题,可是在系统扩展性、总体性能和隔离性方面仍然存在问题。
(1) 系统扩展性方面,元数据存储在NN内存中,受内存上限的制约。
(2) 总体性能方面,吞吐量受单个NN的影响。
(3) 隔离性方面,一个程序可能会影响其余运行的程序,如一个程序消耗过多资源致使其余程序没法顺利运行。HDFS HA本质上仍是单名称节点。HDFS联邦能够解决以上三个方面问题。
在HDFS联邦中,设计了多个相互独立的NN,使得HDFS的命名服务可以水平扩展,这些NN分别进行各自命名空间和块的管理,不须要彼此协调。每一个DN要向集群中全部的NN注册,并周期性的发送心跳信息和块信息,报告本身的状态。
HDFS联邦拥有多个独立的命名空间,其中,每个命名空间管理属于本身的一组块,这些属于同一个命名空间的块组成一个“块池”。每一个DN会为多个块池提供块的存储,块池中的各个块其实是存储在不一样DN中的。
在HDFS中,DataNode 将数据块存储到本地文件系统目录中,具体的目录能够经过配置 hdfs-site.xml 里面的 dfs.datanode.data.dir 参数。在典型的安装配置中,通常都会配置多个目录,而且把这些目录分别配置到不一样的设备上,好比分别配置到不一样的HDD(HDD的全称是Hard Disk Drive)和SSD(全称Solid State Drives,就是咱们熟悉的固态硬盘)上。
当咱们往HDFS上写入新的数据块,DataNode 将会使用volume选择策略来为这个块选择存储的地方。目前Hadoop支持两种volume选择策略:round-robin 和 available space(详情参见:HDFS-1804),咱们能够经过 dfs.datanode.fsdataset.volume.choosing.policy 参数来设置。
循环(round-robin)策略将新块均匀分布在可用磁盘上;而可用空间( available-space )策略优先将数据写入具备最大可用空间的磁盘(经过百分比计算的)。正以下图所示:
默认状况下,DataNode 是使用基于round-robin策略来写入新的数据块。然而在一个长时间运行的集群中,因为HDFS中的大规模文件删除或者经过往DataNode 中添加新的磁盘仍然会致使同一个DataNode中的不一样磁盘存储的数据很不均衡。即便你使用的是基于可用空间的策略,卷(volume)不平衡仍可致使较低效率的磁盘I/O。好比全部新增的数据块都会往新增的磁盘上写,在此期间,其余的磁盘会处于空闲状态,这样新的磁盘将会是整个系统的瓶颈。
Diskbalancer是一个命令行工具,能够在datanode的全部磁盘上均匀分配数据。此工具与Balancer不一样, 后者负责集群范围的数据平衡。因为多种缘由,数据在节点上的磁盘之间可能存在不均匀的扩散。这多是因为大量写入和删除或因为磁盘更换形成的。此工具针对给定的datanode运行,并将块从一个磁盘移动到另外一个磁盘。
---------------------- 正文结束 ------------------------