概述
HDFS(Hadoop Distributed File System ),意为:Hadoop分布式文件系统。
源自谷歌的论文:《TheGoogle File System》,由Doug Cutting 设计实现的。
是Apache Hadoop核心组件之一,作为大数据生态圈最底层的分布式存储服务而存在。
HDFS主要是解决大数据如何存储问题的。分布式意味着是HDFS是横跨在多台计算机上的存储系统。
HDFS是一种能够在普通硬件上运行的分布式文件系统,它是高度容错的,适应于具有大数据集的应用程序,它非常适于存储大型数据 (比如 TB 和 PB)。
HDFS使用多台计算机存储文件, 并且提供统一的访问接口, 像是访问一个普通文件系统一样使用分布式文件系统。
![](https://i-blog.csdnimg.cn/blog_migrate/2bb2dbcec7ef74afdb758aa51d2453fe.png)
特点
优点
支持超大文件
支持超大文件。超大文件在这里指的是几百M,几百GB,甚至几TB大小的文件。一般来说Hadoop的文件系统会存储TB级别或者PB级别的数据。所以在企业的应用中,数据节点有可能有上千个。
检测和快速应对硬件故障
在集群的环境中,硬件故障是常见的问题。因为有上千台服务器连接在一起,这样会导致高故障率。因此故障检测和自动恢复(心跳机制)是hdfs文件系统的一个设计目标。
流式数据访问
HDFS的数据处理规模比较大,应用一次需要访问大量的数据,同时这些应用一般都是批量处理,而不是用户交互式处理。应用程序能以流的形式访问数据集。主要的是数据的吞吐量,而不是访问速度。
简化的一致性模型
大部分hdfs操作文件时,需要一次写入,多次读取。在HDFS中,一个文件一旦经过创建、写入、关闭后,一般就不需要修改了。这样简单的一致性模型,有利于提高吞吐量。
高容错性
数据自动保存多个副本,副本丢失后自动恢复
可构建在廉价机器上
构建在廉价机器上可以轻松的通过扩展机器数量来近乎线性的提高集群存储能力
缺点
低延迟数据访问
低延迟数据。如和用户进行交互的应用,需要数据在毫秒或秒的范围内得到响应。由于Hadoop针对海量数据的吞吐量做了优化,牺牲了获取数据的延迟,所以对于低延迟来说,不适合用hadoop来做。
大量的小文件
HDFS支持超大的文件,是通过数据分布在数据节点,数据的元数据保存在名字节点上。名字节点的内存大小,决定了HDFS文件系统可保存的文件数量。虽然现在的系统内存都比较大,但大量的小文件还是会影响名字节点的性能。
多用户写入文件、修改文件
HDFS的文件只能有一次写入,不支持追加写入(2.0版本支持追加),也不支持修改。只有这样数据的吞吐量才能大。
不支持超强的事务
没有像关系型数据库那样,对事务有强有力的支持。
技术细节
HDFS的架构
![](https://i-blog.csdnimg.cn/blog_migrate/332fd3e5200283a8b8e8070822c1837c.png)
主从架构
HDFS集群是标准的master/slave主从架构集群。
一般一个HDFS集群是有2个Namenode和一定数目的Datanode组成。
Namenode是HDFS主节点,Datanode是HDFS从节点,两种角色各司其职,共同协调完成分布式的文件存储服务。
官方架构图中是一主五从模式,其中五个从角色位于两个机架(Rack)的不同服务器上。
分块存储
HDFS中的文件在物理上是分块存储(block)的,默认大小在Hadoop2.x/3.x版本中是128M,1.x版本中是64M,不足128M则本身就是一块。
块的大小可以通过配置参数来规定,参数位于hdfs-default.xml中:dfs.blocksize。
思考:为什么块的大小不能设置太小,也不能设置太大?
HDFS的块设置太小,会增加寻址时间,程序一直在找块的开始位置;
如果块设置的太大,从磁盘传输数据的时间会明显大于定位这个块开始位置所需的时间。导致程序在处理这块数据时,会非常慢。
总结:HDFS块的大小设置主要取决于磁盘传输速率。
![](https://i-blog.csdnimg.cn/blog_migrate/599a00db36fb28623dc9ba01e2495ee4.png)
- 副本机制
文件的所有block都会有副本。副本系数可以在文件创建的时候指定,也可以在之后通过命令改变。
副本数由参数dfs.replication控制,默认值是3,也就是会额外再复制2份,连同本身总共3份副本。
- 元数据记录
在HDFS中,Namenode管理的元数据具有两种类型:
文件自身属性信息
文件名称、权限,修改时间,文件大小,复制因子,数据块大小。
文件块位置映射信息
记录文件块和DataNode之间的映射信息,即哪个块位于哪个节点上。
- 抽象统一的目录树结构(namespace)
HDFS支持传统的层次型文件组织结构。用户可以创建目录,然后将文件保存在这些目录里。文件系统名字空间的层次结构和大多数现有的文件系统类似:用户可以创建、删除、移动或重命名文件。
Namenode负责维护文件系统的namespace名称空间,任何对文件系统名称空间或属性的修改都将被Namenode记录下来。
HDFS会给客户端提供一个统一的抽象目录树,客户端通过路径来访问文件,形如:hdfs://namenode:port/dir-a/dir-b/dir-c/file.data。
Block
数据块(Block)是HDFS中存储文件的最基本的存储单位
当在HDFS上存储超大文件时,HDFS会以一个标准将文件切分成几块,分别存储到不同的节点上,切出的数据就称为Block。
Block 默认的大小在Hadoop1.0中是64M,在Hadoop2.0中是128M
切块的优点:
文件块可以保存在不同的节点上
简化存储系统。这样不需要管理文件,而是管理文件块
有利于数据的复制。
在HDFS中,如果一个文件小于一个数据块的大小,并不占用整个数据块存储空间
NameNode
NameNode维护HDFS中的元数据信息:
文件和Block之间关系的信息
Block数量信息
Block和DataNode之间的关系信息
元数据格式参照:FileName replicas block-Ids id2host。例如:/test/a.log, 3, {b1,b2}, [{b1:[h0,h1,h3]}, {b2:[h0,h2,h4]}]
NameNode通过RPC心跳机制监测DataNode
每一条元数据大概是150B大小
元数据信息存储在内存以及文件中,内存中为实时信息,这样做的目的是为了快速查询
元数据信息会持久化到NameNode节点的硬盘上,持久化目录的路径是由core-site.xml的dfs.tmp.dir属性来决定的。此参数如果不配置,默认是放在/tmp
存储元数据的目录:dfs/name/current
持久化的文件包括:
fsimage:元数据镜像文件。存储某NameNode元数据信息,并不是实时同步内存中的数据。
edits:操作日志文件,记录了NameNode所要执行的操作
fstime:保存最近一次checkpoint的时间
当有写请求时,NameNode会首先写该操作先写到磁盘上的edits文件中,当edits文件写成功后才会修改内存,并向客户端返回成功信号,而此时fsimage中的数据并没有发生改动。所以,fsimage中的数据并不是实时的数据,而是在达到条件时再进行更新,更新过程需要SecondaryNameNode参与
无论是Hadoop1.0还是2.0,当HDFS启动,NameNode会做一次edits和fsimage合并的操作。这样做的目的是确保fsimage里的元数据更新。
可以通过指令手动合并:hadoop dfsadmin -rollEdits
当HDFS启动的时候,NameNode会将fsimage中的元数据信息加载到内存中
当HDFS启动时,每个DataNode会向NameNode汇报自身的存储的信息,比如存储了哪些文件块,块大小,块id等。NameNode收到这些信息之后,会做汇总和检测,检测数据是否完整,复本数量是否达到要求,如果检测出现问题,HDFS会进入安全模式,在安全模式做数据或副本的复制,直到修复完成后,安全模式自动退出。
如果HDFS处于安全模式,只能对外读服务,不能写服务。
DataNode
在HDFS中,数据是存放在DataNode上面的,并且是以Block的形式存储的
存储Block的目录:dfs/data/current/BP-1998993700-192.168.150.137-1537051327964/current/finalized/subdir0/subdir0
DataNode节点会不断向NameNode节点发送心跳报告
在HDFS启动的时候,每个DataNode将当前存储的数据块信息告知NameNode节点
DataNode通过向NameNode主动发送心跳保持与其联系,默认是每隔3秒发送一次心跳信息
心跳信息包含这个节点的状态以及数据块信息
如果10分钟都没收到dn的心跳,则认为其已经lost,那么NameNode会copy这个DataNode上的Block到其他DataNode上
在HDFS中,DataNode上存储的复本Replication是多复本策略。默认是三个
如果是伪分布式模式,副本只能配置1个,因为如果副本数量>1,会导致HDFS一致处于安全模式而不能退出
复本放置策略
第一个副本:如果是集群内部提交,那么哪一个DataNode提交的就将该复本放在哪个节点上。如果是集群之外的客户端上传的数据,那么就随机选择一台磁盘不太满,cpu不太忙的节点进行存储
第二个副本:放置在第一个复本不同机架的节点上
第三个副本:放置在与第二个副本相同机架的节点上
更多副本:随机节点(哪个节点比较空闲,就放到哪个节点上)