HDFS原理解析
- 一、HDFS概述
- 1.1 介绍
- 1.2 历史
- 二、HDFS优缺点
- 三、HDFS应用场景
- 3.1 适合的应用场景
- 3.2 不适合的应用场景
- 四、HDFS的架构
- 4.1 Client
- 4.2 NameNode
- 4.3 DataNode
- 4.4 Secondary NameNode
- 五、NameNode和DataNode详解
- 5.1 NameNode作用
- 5.2 DataNode作用
- 六、HDFS的副本机制
- 七、安全模式
- 八、HDFS读写流程
- 8.1 HDFS文件写入流程
- 8.2 HDFS文件读取流程
- 九、网络拓扑与机架感知
- 9.1 引入
- 9.2 网络拓扑
- 9.3 机架感知
- 十、NameNode工作机制
- 10.1 NameNode 元数据的存储位置
- 10.2 Fsimage
- 10.3 edits
- 10.4 NameNode 工作机制
- 十一、Secondary NameNode 工作机制
- 11.1 2NN 工作机制
- 11.2 check point
- 十二、HDFS Shell 操作
- 十三、HDFS的高可用机制
- 13.1 HDFS高可用介绍
- 13.2 组件介绍
- 十四、Hadoop的联邦机制(Federation)
- 14.1 背景概述
- 14.2 Federation架构设计
一、HDFS概述
1.1 介绍
在现代的企业环境中,单机容量往往无法存储大量数据,需要跨机器存储。统一管理分布在集群上的文件系统称为分布式文件系统
。
HDFS(Hadoop Distributed File System)
是 Apache Hadoop 项目的一个子项目。Hadoop 非常适于存储大型数据 (比如 TB 和 PB), 其就是使用 HDFS 作为存储系统。 HDFS 使用多台计算机存储文件, 并且提供统一的访问接口, 像是访问一个普通文件系统一样使用分布式文件系统。
1.2 历史
- Doug Cutting 在做 Lucene 的时候, 需要编写一个爬虫服务, 这个爬虫写的并不顺利, 遇到了一些问题, 诸如:
如何存储大规模的数据, 如何保证集群的可伸缩性, 如何动态容错等 - 2013年的时候, Google 发布了三篇论文, 被称作为三驾马车, 其中有一篇叫做 GFS, 是描述了 Google 内部的一个叫做
GFS 的分布式大规模文件系统, 具有强大的可伸缩性和容错性 - Doug Cutting 后来根据 GFS 的论文, 创造了一个新的文件系统, 叫做 HDFS
二、HDFS优缺点
- 优点
- 高容错性
- 数据自动保存多个副本
- 某个副本丢失后,可自动回复
- 适合大数据处理
- 数据规模大
- 文件规模大
- 可以运行在廉价的pc机上
- 缺点
- 不适合低延时数据访问
- 无法高效存储小文件
- 一个block块在NameNode中占150byte(固定),过多小文件会占用NameNode内存
- 小文件的寻址时间大于读取时间,不符合HDFS设计目标
- 不支持并发写和随机写
- 一个文件只能有一个写,不允许多线程同时写
- 不支持随机写,但支持追加写
三、HDFS应用场景
3.1 适合的应用场景
- 存储非常大的文件:这里非常大指的是几百M、G、或者TB级别,需要
高吞吐量
,对延时没有要求
。 - 采用流式的数据访问方式: 即
一次写入、多次读取
,数据集经常从数据源生成或者拷贝一次,然后在其上做很多分析工作 。 - 运行于商业硬件上: Hadoop不需要特别贵的机器,可运行于普通廉价机器,可以处
节约成本
- 需要高容错性
- 为数据存储提供所需的
扩展能力
3.2 不适合的应用场景
- 低延时的数据访问 对延时要求在毫秒级别的应用,不适合采用HDFS。HDFS是为高吞吐数据传输设计的,因此可能
牺牲延时
- 大量小文件 文件的元数据保存在
NameNode的内存中
, 整个文件系统的文件数量会受限于NameNode的内存大小。
经验而言,一个文件/目录/文件块一般占有150字节的元数据内存空间。如果有100万个文件,每个文件占用1个文件块,则需要大约300M的内存。因此十亿级别的文件数量在现有商用机器上难以支持。 - 多方读写,需要任意的文件修改HDFS采用追加(append-only)的方式写入数据。
不支持文件任意owset的修改
。不支持多个写入器(writer)
四、HDFS的架构
HDFS是一个 主/从(Mater/Slave)
体系结构 ,
HDFS由四部分组成,HDFS Client、NameNod e、DataNode
和Secondary NameNode
。
4.1 Client
就是客户端
- 文件切分。文件上传 HDFS 的时候,Client 将文件切分成 一个一个的Block,然后进行存储。
- 与 NameNode 交互,获取文件的位置信息。
- 与 DataNode 交互,读取或者写入数据。
- Client 提供一些命令来管理 和访问HDFS,比如启动或者关闭HDFS。
4.2 NameNode
就是 master,它是一个主管、管理者
- 管理 HDFS 的名称空间
- 管理数据块(Block)映射信息
- 配置副本策略
- 处理客户端读写请求。
4.3 DataNode
就是Slave。NameNode 下达命令,DataNode 执行实际的操作。
- 存储实际的数据块。
- 执行数据块的读/写操作。
4.4 Secondary NameNode
并非 NameNode 的热备。当NameNode 挂掉的时候,它并不能马上替换 NameNode 并提供服务。
- 辅助 NameNode,分担其工作量。
- 定期合并 fsimage和fsedits,并推送给NameNode。
- 在紧急情况下,可辅助恢复 NameNode。
五、NameNode和DataNode详解
5.1 NameNode作用
- NameNode在内存中保存着整个文件系统的名称 空间和文件数据块的地址映射
- 整个HDFS可存储的文件数受限于NameNode的内存大小
- NameNode是HDFS的核心
- NameNode也称为Master
- NameNode存储HDFS的元数据:文件系统中所有的目录树,并跟踪整个集群的文件
- NameNode不存储实际数据
- NameNode知道HDFS中任何给定文件的块列表及其位置,使用此信息NameNode知道如何从块中构建文件
- NameNode不持久化存储每个文件中各个块所在的节点信息,这些信息会会在系统启动时从块中数据节点重建
- NameNode关闭,集群将无法访问
- NameNode所在的机器通常配置大量内存
5.2 DataNode作用
提供真实文件数据的存储服务。
- DataNode负责将实际数据存储在HDFS中
- DataNode也称为Slave
- NameNode和DataNode会保持不断通信
- DataNode启动时,会将自己发布到NameNode并汇报自己负责的块列表
- 某个DataNode关闭不会影响集群的正常使用
- DataNode每个3秒向NameNode发送心跳,若NameNode长时间(10分钟)没有接受到DataNode发送的心跳则认为该节点不可用,会将该节点的数据复制到其他节点,并且永远不再使用该节点(退出集群后再次上线可以恢复)
- DataNode所在的机器通常配置大量磁盘空间
六、HDFS的副本机制
所有的文件都是以 block 块的方式存放在 HDFS 文件系统当中,作用如下
- 一个文件有可能大于集群中任意一个磁盘,引入块机制,可以很好的解决这个问题
- 使用块作为文件存储的逻辑单位可以简化存储子系统
- 块非常适合用于数据备份进而提供数据容错能力
在 Hadoop1 当中, 文件的 block 块默认大小是 64M, hadoop2 当中
, 文件的 block 块大小默认是128M
, block 块的大小可以通过 hdfs-site.xml 当中的配置文件进行指定
<property>
<name>dfs.block.size</name>
<value>块大小 以字节为单位</value>
</property>
七、安全模式
安全模式是HDFS所处的一种特殊状态,在这种状态下,文件系统只接受读数据请求,而不接受创建、删除、修改等变更请求。同时会对数据块进行大量校验,导致资源的分配和申请耗时远超预期。
在NameNode主节点启动时,HDFS首先进入安全模式,DataNode在启动的时候会向namenode汇报可用的block等状态,当整个系统达到安全标准时,HDFS自动离开安全模式。如果HDFS处于安全模式下,则文件block不能进行任何的副本复制操作,hdfs集群刚启动的时候,默认30S钟的时间是出于安全期的,只有过了30S之后,集群脱离了安全期,然后才可以对集群进行操作
safemode阈值由dfs.namenode.safemode.threshold-pct参数控制(缺省0.999),每个块的满足需求最小副本数由dfs.namenode.replication.min参数控制。因此在业务紧急要求恢复的时候,可以尝试将以下两个参数调低,使安全模式尽快结束:
dfs.namenode.replication.min——满足需要的最小副本数
dfs.namenode.safemode.threshold-pct——集群中满足正常配置的数据块比例
如果是为了防止某些异常数据导致始终校验不过的情况,可以尝试将上面的dfs.namenode.safemode.threshold-pct参数调为0或比0小的值后重启NameNode,这样永远不会进入安全模式;或者使用以下命令手动退出安全模式
hdfs dfsadmin -safemode
查看
hdfs dfsadmin -safemode get
离开
hdfs dfsadmin -safemode leave
八、HDFS读写流程
8.1 HDFS文件写入流程
- Client 发起文件上传请求, 通过 RPC 与 NameNode 建立通讯, NameNode 检查目标文件是否已存在,父目录是否存在, 返回是否可以上传
- Client 请求第一个 block 该传输到哪些 DataNode 服务器上
- NameNode 根据配置文件中指定的备份数量及机架感知原理进行文件分配, 返回可用的DataNode 的地址如: A, B, CHadoop 在设计时考虑到数据的安全与高效, 数据文件默认在 HDFS 上存放三份, 存储策略为本地一份, 同机架内其它某一节点上一份, 不同机架的某一节点上一份。
- Client 请求 3 台 DataNode 中的一台 A 上传数据(本质上是一个 RPC 调用,建立 pipeline), A 收到请求会继续调用 B, 然后 B 调用 C, 将整个 pipeline 建立完成, 后逐级返回 client
- Client 开始往 A 上传第一个 block(先从磁盘读取数据放到一个本地内存缓存), 以packet 为单位(默认64K), A 收到一个 packet 就会传给 B, B 传给 C. A 每传一个 packet 会放入一个应答队列等待应答
- 数据被分割成一个个 packet 数据包在 pipeline 上依次传输, 在 pipeline 反方向上, 逐个发送 ack(命令正确应答), 最终由 pipeline 中第一个 DataNode 节点 A 将 pipelineack 发送给 Client
- 当一个 block 传输完成之后, Client 再次请求 NameNode 上传第二个 block 到服务 1
8.2 HDFS文件读取流程
- Client向NameNode发起RPC请求,来确定请求文件block所在的位置;
- NameNode会视情况返回文件的部分或者全部block列表,对于每个block,NameNode 都会返回含有该 block 副本的 DataNode 地址; 这些返回的 DN 地址,会按照集群拓扑结构得出 DataNode 与客户端的距离,然后进行排序,排序两个规则:网络拓扑结构中距离Client 近的排靠前;心跳机制中超时汇报的 DN 状态为 STALE,这样的排靠后;
- Client 选取排序靠前的 DataNode 来读取 block,如果客户端本身就是DataNode,那么将从本地直接获取数据(短路读取特性);
- 底层上本质是建立 Socket Stream(FSDataInputStream),重复的调用父类DataInputStream 的 read 方法,直到这个块上的数据读取完毕;
- 当读完列表的 block 后,若文件读取还没有结束,客户端会继续向NameNode 获取下一批的 block 列表;
- 读取完一个 block 都会进行 checksum 验证,如果读取 DataNode 时出现错误,客户端会通知 NameNode,然后再从下一个拥有该 block 副本的DataNode 继续读。
- read 方法是并行的读取 block 信息,不是一块一块的读取;NameNode 只是返回Client请求包含块的DataNode地址,并不是返回请求块的数据;
- 最终读取来所有的 block 会合并成一个完整的最终文件。
九、网络拓扑与机架感知
9.1 引入
客户端上传数据到HDFS时,会上传到离当前客户端最近的数据节点,因此通过网络拓扑获取网络中的距离
9.2 网络拓扑
- 同一节点上的进程距离为0
- 同一机架上的不同节点距离为2
- 同一数据中心不同机架的节点距离为4
- 不同数据中心的节点距离为6
9.3 机架感知
以三个副本为例,第一个副本根据放在距离客户端最近的一个节点,第二个副本放在该节点同一机架的不同节点,第三个副本放在不同机架的随机节点
十、NameNode工作机制
10.1 NameNode 元数据的存储位置
首先,为了提高HDFS的读写速率,必定将NameNode的元数据存储在内存中,但是内存一旦断电元数据将丢失,因此必须将内存中的元数据存储在磁盘中用于备份
10.2 Fsimage
Fsimage为内存元数据的备份。若内存的元数据发生改变,如果同时更新Fsimage会降低效率,如果不更新会发生数据不一致问题
10.3 edits
针对上述问题,最终逻辑是不更新Fsimage文件,为解决数据不一致问题,引入edits文件,该文件只记录操作并且采用追加写 的形式,即每当内存的元数据发生改变的同时记录本次操作记录追加到磁盘中的edits,这样内存元数据等于磁盘的Fsimage + edits
10.4 NameNode 工作机制
当NameNode启动时先滚动edits并生成一个空的edits.inprogress会将Fsimage和edits文件加载到内存中进行合并,之后的操作(增删)将追加到edits.inprogress中
十一、Secondary NameNode 工作机制
11.1 2NN 工作机制
根据NameNode的工作机制,当edits的操作记录记录过多时不仅会降低追加效率,同时断电恢复时会花费大量时间,因此2NN将针对此问题进行解决,将触发检查条件时,2NN首先通知NameNode滚动edits生成新的eidts.inprogress(之后的操作记录将写在此文件)并通过http get的形式将磁盘的Fsimage和edits复制过来并加载到内存中进行合并,生成Fsimage.chkpoint文件,并通过http post形式拷贝给NameNode重命名为Fsimage后替换原来的Fsimage。
11.2 check point
- 每个一个小时执行一次
<property>
<name>dfs.namenode.checkpoint.period</name>
<value>3600</value>
</property>
- 100万次操作执行一次(一分钟检查一次操作数)
<property>
<name>dfs.namenode.checkpoint.txns</name>
<value>1000000</value>
<description>操作动作次数</description>
</property>
<property>
<name>dfs.namenode.checkpoint.check.period</name>
<value>60</value>
<description> 1分钟检查一次操作次数</description>
</property>
十二、HDFS Shell 操作
shell | |||
hadoop fs -ls path | -h 转换显示的字节数单位 | -R 递归显示 | 显示文件、目录信息 |
hadoop fs -mkdir path | -p 创建多级文件 | 在hdfs上创建目录 | |
hadoop fs -put src dst | -f 覆盖原文件上传 | -p 保留文件的信息 | 上传本地文件到hdfs |
hadoop fs -get src dst | -crc 为下载的文件写CRC校验和 | -f 覆盖原文件下载 | 下载hdfs文件到本地 |
hadoop fs -appendToFile src dst | 将一个文件追加到另一个文件之后 | ||
hadoop fs -cat path | 显示hdfs文件内容到控制台 | ||
hadoop fs -tail path | -f 监测文件追加的数据 | 显示最后一千字节内容 | |
hadoop fs -chgrp path | -R 递归修改 | 修改文件组 | |
hadoop fs -chmod path | -R 递归修改 | 修改文件权限 | |
hadoop fs -chown path | 修改文件所有者 | ||
hadoop fs -copyFromLocal src dst | 从本地文件系统拷贝文件到hdfs(类似-put) | ||
hadoop fs -copyToLocal src dst | 从hdfs文件拷贝到本地文件系统(类似-get) | ||
hadoop fs -cp path1 path2 | 从hdfs一个路径复制到另一个路径 | ||
hadoop fs -mv path1 path2 | 在hdfs目录中移动文件(剪切) | ||
hadoop fs -rm path | -r 递归删除 | 删除hdfs文件(夹) | |
hadoop fs -df path | -h 换单位 | 统计文件系统可用空间信息 | |
hadoop fs -du path | -h 换单位 | 显示文件大小 | |
hadoop fs -setrep | -R 递归改变 | 设置文件的副本数(优先级最高) | |
hadoop fs -help | 帮助文档 | ||
hadoop fs -count path | 统计当前路径文件夹个数,算上自身 | ||
hadoop fs -touchz file | 创建空白文件 |
十三、HDFS的高可用机制
13.1 HDFS高可用介绍
在Hadoop 中,NameNode 所处的位置是非常重要的,整个HDFS文件系统的元数据信息都由NameNode 来管理,NameNode的可用性直接决定了Hadoop 的可用性,一旦NameNode进程不能工作了,就会影响整个集群的正常使用。在典型的HA集群中,两台独立的机器被配置为NameNode。在工作集群中,NameNode机器中的一个处于Active状态,另一个处于Standby状态
。Active NameNode负责群集中的所有客户端操作,而Standby充当从服务器。Standby机器保持足够的状态以提供快速故障切换(如果需要)。
13.2 组件介绍
ZKFailoverController
是基于Zookeeper的故障转移控制器,它负责控制NameNode的主备切换,ZKFailoverController会监测NameNode的健康状态,当发现Active NameNode出现异常时会通过Zookeeper进行一次新的选举,完成Active和Standby状态的切换
HealthMonitor
周期性调用NameNode的HAServiceProtocol RPC接口(monitorHealth 和 getServiceStatus),监控NameNode的健康状态并向ZKFailoverController反馈
ActiveStandbyElector
接收ZKFC的选举请求,通过Zookeeper自动完成主备选举,选举完成后回调ZKFailoverController的主备切换方法对NameNode进行Active和Standby状态的切换.
DataNode
NameNode包含了HDFS的元数据信息和数据块信息(blockmap),其中数据块信息通过DataNode主动向Active NameNode和Standby NameNode上报
共享存储系统
共享存储系统负责存储HDFS的元数据(EditsLog),Active NameNode(写入)和 StandbyNameNode(读取)通过共享存储系统实现元数据同步,在主备切换过程中,新的ActiveNameNode必须确保元数据同步完成才能对外提供服务
十四、Hadoop的联邦机制(Federation)
14.1 背景概述
单NameNode的架构使得HDFS在集群扩展性和性能上都有潜在的问题,当集群大到一定程度后,NameNode进程使用的内存可能会达到上百G,NameNode成为了性能的瓶颈。因而提出了namenode水平扩展方案-- Federation。Federation中文意思为联邦,联盟,是NameNode的Federation,也就是会有多个NameNode。多个NameNode的情况意味着有多个namespace(命名空间),区别于HA模式下的多NameNode,它们是拥有着同一个namespace。既然说到了NameNode的命名空间的概念,这里就看一下现有的HDFS数据管理架构,如下图所示:
从上图中,我们可以很明显地看出现有的HDFS数据管理,数据存储2层分层的结构.也就是说,所有关于存储数据的信息和管理是放在NameNode这边,而真实数据的存储则是在各个DataNode下.而这些隶属于同一个NameNode所管理的数据都是在同一个命名空间下的.而一个namespace对应一个block pool。Block Pool是同一个namespace下的block的集合.当然这是我们最常见的单个namespace的情况,也就是一个NameNode管理集群中所有元数据信息的时候.如果我们遇到了之前提到的NameNode内存使用过高的问题,这时候怎么办?元数据空间依然还是在不断增大,一味调高NameNode的jvm大小绝对不是一个持久的办法.这时候就诞生了HDFS Federation的机制.
14.2 Federation架构设计
HDFS Federation是解决namenode内存瓶颈问题的水平横向扩展方案。
Federation意味着在集群中将会有多个namenode/namespace。这些namenode之间是联合的,也就是说,他们之间相互独立且不需要互相协调,各自分工,管理自己的区域。分布式的datanode被用作通用的数据块存储存储设备。每个datanode要向集群中所有的namenode注册,且周期性地向所有namenode发送心跳和块报告,并执行来自所有namenode的命令。
Federation一个典型的例子就是上面提到的NameNode内存过高问题,我们完全可以将上面部分大的文件目录移到另外一个NameNode上做管理.更重要的一点在于,这些NameNode是共享集群中所有的DataNode的,它们还是在同一个集群内的
。这时候在DataNode上就不仅仅存储一个Block Pool下的数据了,而是多个(在DataNode的datadir所在目录里面查看BP-xx.xx.xx.xx打头的目录)。
概括起来:
- 多个NN共用一个集群里的存储资源,每个NN都可以单独对外提供服务。
- 每个NN都会定义一个存储池,有单独的id,每个DN都为所有存储池提供存储。
- DN会按照存储池id向其对应的NN汇报块信息,同时,DN会向所有NN汇报本地存储可用资源情况。
HDFS Federation不足之处
HDFS Federation并没有完全解决单点故障问题。虽然namenode/namespace存在多个,但是从单个namenode/namespace看,仍然存在单点故障:如果某个namenode挂掉了,其管理的相应的文件便不可以访问。Federation中每个namenode仍然像之前HDFS上实现一样,配有一个secondary namenode,以便主namenode挂掉一下,用于还原元数据信息。
所以一般集群规模真的很大的时候,会采用HA+Federation
的部署方案。也就是每个联合的namenodes都是ha
的。