简介
Hadoop Distributed File System(HDFS)被设计使用于运行在廉价硬件之上。基本概念上与通用的文件系统很相似,但是和一般的分布式文件系统却有着很重要的区别。HDFS是高容错的,高吞吐的以及适用于有着大量数据集的应用。HDFS放宽了POSIX的一些要求,以支持对文件系统数据的流访问。
设计目标
- 硬件故障
- 流式数据访问
- 大数据集
- 简单一致性模型
- Moving Computation is Cheaper then Moving data
- 跨异构硬件和软件平台的访问概率
硬件故障
HDFS的实例一般是是有数以百计的服务器组成,每一台服务器都存储整个文件系统的部分数据。大量的组建以及每一个组建都有很有可能会因为一些组建的故障而无法正常工作。因此,快速检测故障以及自动恢复成为核心的设计目标之一。流式数据访问
和一般的使用应用程序不同,使用HDFS的应用通常想要通过流式访问存储于HDFS中的数据。因而,HDFS被设计用于批处理而不是交互式的处理。
HDFS的核心点是高吞吐而非低延迟。大数据集
HDFS应该在一台实例中支持数以千万的文件。简单一致性模型
HDFS应用需要给予文件提供一次写入多次读取的访问模型。文件一旦创建、写入、以及关闭之后,除了追加以及截断,其他的操作均不被允许。
追加:HDFS上的文件允许被在文件的结尾进行追加,而不被允许在文件的任意位置上进行更新操作。这种假设简化了数据一致性问题,以及确保了数据访问的高吞吐量。Moving Computation is Cheaper then Moving data
当应用程序进行计算提交的时候,将计算的执行下放到数据存储的位置进行操作,是非常高效的。特别是,当操作的数据量级非常大的时候。
下放计算的操作可以有效的降低网络拥塞以及增加系统整体的吞吐量。
假设:将计算迁移到离数据的存放位置而不是,移动数据当程序正在进行的时候。HDFS提供响应的接口,是的可以将应用程序自身下放到数据的落点位置(NodeManager)。NameNode(s)和DataNodes
HDFS有着主从架构,一个HDFS集群由单一的(提供服务的)NameNode组成,NameNode作为主服务器管理者这个系统的命民空间以及控制这来自于客户端的访问文件请求。另外,DataNode(集群中的每一个node)运行这存储管理服务。
HDFS提供文件系统命民空间以及允许用户将数据以文件的形式存储起来。在HDFS内部,存储文件的时候,会将一个文件拆分至一个或多个块(block)当中,然后将这些块分散存储到集群的每一台DataNode当中。NameNode
NameNode向客户端提供执行文件系统民命空间的操作,例如打开、关闭以及重命名。NameNode还存储这每一个block到DataNodes的映射关系。DataNode
DataNode负责处理来自于文件系统客户端的读写请求。提供以下操作:block的创建、删除以及来自于NameNode的备份指令。
单一NameNode的存在极大的简化了系统的架构。NameNode作为整个系统的管理者,且存储这整个HDFS的元数据。该架构设计的一个目的是,使得用户的数据绝不会流经NameNode。文件系统命名空间
HDFS类似于传统的文件系统。
- 用户可以创建目录在目录下存储文件。
- 另外,HDFS提供用户配额(user quotas)以及访问权限(access permissions)。
- HDFS不支持硬链接和软链接
-
数据复制
HDFS被设计用于在一个集群中跨机器的存储非常大的文件。将文件存储为一个block序列。为了确保容错性,这些blocks将会被复制。block的大小和复制因子对于每一个文件都是可配置的。
一个文件中除了最后一个块之外的所有块的大小都相同,而在添加了对可变长度块的支持后,用户可以在不填写配置块大小的最后一个块的情况下开始一个新块。
用户可以制定文件的副本数。副本因子可以在文件创建的而时候指明,以及在随后可以被更改。HDFS中的文件是一次写的(除了追加和截断),并且在任何时候都有一个严格的写入器。
NameNode负责所有关于块复制的决策。它定期接收集群中每个datanode的Heartbeat和Blockreport。如果接收到Heartbeat,则表示DataNode正常。一个Blockreport包含一个DataNode上所有block的列表。
副本存放点
副本的存放点对于HDFS的可靠性和性能至关重要。机架感知策略对于数据的可靠性,有效性和带宽利用。
HDFS中的实例一般都横跨许多机架,结点之间进行通信的话,如果在不同的机架之间,需要通过交换机进行通信。通常情况下,在相同机架中的带宽要远高于不同的机架。
NameNode中保存着每一个DataNode的机架id。一个简单但非最佳的策略是将副本放置在唯一的机架上。这可以防止在整个机架出现故障时丢失数据,并允许占用在读取数据时使用来自多个机架的带宽。这种策略的实行最终将副本分散在集群当中,可以在组件失败的时候有效的进行负载均衡。唯一的代价是会增加写入成本,因为写入需要将block传送到多个机架上面。
一般情况下,且写入的节点是DataNode的时候,HDFS将在本地放置一个副本(副本因子是3)负责将会随即在相同的机架上找一个DataNode将副本写入。副本选择
为了降低计算的总带宽以及读延迟,HDFS将会采用,提供集群中最靠近发出读请求的的机器的副本。
文件系统的元数据持久化
HDFS的命名空间将会存储于NameNode当中,NameNode采用EditLog作为事务日至持久化存储每一条发生在文件系统当中的更改。例如:创建一个新的文件,将会在NameNode中插入一条日至,这条日至将会在EditLog中被指明。
HDFS的文件系统命名空间将被存储于一个叫做FsImage的文件当中,这个文件中包含了块到文件的映射以及文件系统的属性。NameNode的作用
NameNode将整个文件系统的命名空间以及文件的块映射存储到内存当中。当NameNode启动的时候,或者checkpoint被出发的时候(配置项),NameNode将会从FsImage以及EditLog中(硬盘中的)加载全部的事务操作,以及将新的事务操作日至,下放到FsImage当中。
NameNode可以在加载EditLog的过程中截断旧的EditLog(抛弃已经应用的事务),因为这些事务以及被应用到了FsImage当中。这种操作,被称之为checkpoint。
checkpoint的目的是为了确保HDFS以及将文件系统元数据的视图快照化,并将当前文件系统的元数据写入到(新的)FsImage当中。虽然直接读取FsImage是非常高效的,但是频繁的对FsImage进行增量写入的效率却是非常底下的,对于对FsImage进行的修改操作,我们将会将这部分(还没有应用持久化到下一周期的FsImage当中)先写入到EditLog当中。当进行checkpoint的时候,这部分的修改将会被应用到FsImage当中(checkpoint将会周期性的进行)。DataNode的作用
DataNode将会在DataNode的本地文件系统当中存储HDFS的(离散)数据。DataNode对于HDFS上面的文件是一点都不了解的。它只会将一个文件的分块(block of file)存储到自己的本地文件系统。DataNode不会将所有的文件都创建在同一个目录当中,而是通过启发式创建每个目录下的(当前最佳数量的)的文件以及(合适数量的)子目录。在相同本地文件系统中创建的文件数可能不是最佳的,因为在本地文件系统当中无法进行有效的确定在单一文件夹中文件的数量。当一个DataNode启动的时候,他会嫂面本地文件系统,生成HDFS的数据block列表(这些列表与本地文件相关联),并将该列表相NameNode进行汇报(该报表本称之为BlockReport)。
数据结构
Data Blocks
通常HDFS当中一个block被设置为128MB。因此,一个HDFS文件被且分成一个一个的(大小为128MB的)块,随后如果集群设定的当的话,将会将这些块分散在不同的DataNode当中。
副本管道
当客户端对HDFS进行写入的时候,NameNode将会对DataNode汇报的block列表进行检索。客户端将会通过NameNode提供的列表对第一个DataNode进行写入。(三副本策略)
第一个DataNode开始接收数据的每一部分,
- 将接收到的没一部分写入本地仓库,
- 随后每接收到一部分,就将接收当的数据传递到列表中的第二个机器当中。
以此类推。
- 当最后一个DataNode接收到数据,并将数据写入到本地文件系统当中之后,回送写入成功的消息。
空间回收
文件删除和取消删除
如果开启了回收站的选项,将要删除的文件并不会立即从HDFS中移除,而是将该文件移动到回收站目录当中(每个用户都有自己的回收站:/user/<username>/.Trash
)。因此,只要文件还保存在回收站,就可以被快速恢复回来。降低副本因子
当文件的复制因子减少时,NameNode 会选择可以删除的多余副本。下一个 Heartbeat 将此信息传输到 DataNode。然后DataNode移除相应的块,相应的空闲空间出现在集群中。同样,在 setReplication API 调用完成与集群中出现可用空间之间可能存在时间延迟。