第二节 HDFS概念
Posted fkbush
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第二节 HDFS概念相关的知识,希望对你有一定的参考价值。
Block(前文翻译的“块”,以后还是使用原文的block)
磁盘的block大小,是可以读写的最小单位。单一磁盘文件系统处理这些block中的数据,
它通常是磁盘block大小的整数倍。文件系统的block大小通常是几kb,而磁盘block通常是
512b。这对于只是简单读写任意长度文件的文件系统使用者来说是透明的。尽管如此,
还是有一些工具来维护文件系统,如df和fsck,它是在文件系统的block级别操作的。
HDFS同样有block的概念,但是它是一个更大的单元----默认128M。如同单一磁盘
的文件系统,HDFS中的文件也分解成block大小的数据块,独立保存在各单元中。不
像单一磁盘文件系统,如果HDFS中的文件比block小,它不会占用block的整个存储空间
(例如,一个1M的文件存储在128M的block中,它只使用1M的磁盘空间而不是128M)。
如果没有特别指明,本书的block指的是HDFS的block。
对于分布式文件系统有一个block抽象带来了几个好处。第一个显而易见的好处是:一
个文件可以比网络中的任意一个磁盘更大。不需要文件的所有block保存在同一个磁盘上,
所以它们可以使用集群上的任意一个磁盘。实际上,一个文件的block可以占用集群上的
所有磁盘,尽管这不常见。
第二,抽象block而不是抽象文件简化了子系统的存储。简易性是所有系统追求的东西,
但是它对失败方式多样化的分布式系统尤其重要。存储子系统使用block,简化了存储管理(
因为block是固定大小,它可以简单计算出在给定的磁盘上可以存储多少block)并且消除
元数据关注点(因为block只是要存储的数据块,象权限信息等文件元数据不需要存储,所以
其它的系统可以单独处理元数据)。
此外,block很适合复制以提供容错和可用性。为了防止block和磁盘毁坏、机器故障等,
每一个block都被复制到一些物理分离的机器上(典型3个)。如果一个block不可用,可以从
别一个位置读取备份,这对客户端来说是透明的。由于毁坏或机器故障而不可用的block可以
从其它可用的机器上再拷贝一份从而让备份因子回到正常水平(见97页数据整合来看更多的
数据毁坏防范)。同样的,一些应用会对于经常读取的文件的block设置高复制因子。如同
它的堂兄弟fs,HDFS的命令fsck知道block。例如,运行以下命令:
% hdfs fsck / -files -blocks会显示文件系统中构成文件的block列表。
Namenode和Datanode
在master-worker模式中,HDFS集群有两种节点操作:一个namenode(master)和一些
datanode(worker)。namenode管理文件系统命名空间。它维护文件系统的树结构,树中
有所有文件和目录的元数据信息。这些信息以两种形式保存在本地磁盘上:命名空间镜像
和编辑日志。namenode也知道给定的文件的所有block在哪个datanode上;但是,它不存
储block地址,因为这个信息在系统重启后会被重新构造。
客户端通过与namenode和datanode交互来代表用户访问文件系统。客户端提供了一个
文件系统接口,与可移植操作系统接口相似,所以用户函数不需要知道namenode和datanode。
datanode是文件系统中干重活的。他们存储、搜索block(当客户端或namenode让它去做时),
它周期性向namenode汇报它所存储的block列表。
没有namenode,文件系统就无法使用。事实上,如果机器的namenode被消除,它上面的
文件系统中的所有文件都会丢失,因为无法根据datanode上的block来知道如何重构文件。基
于这个原因,让namenode可以从故障中恢复是很重要的,HADOOP为它提供了两种方法。
第一种方式是备份存有文件系统元数据的持久状态的文件。HADOOP可以配置来把它的
namenode的持久状态写到不同的文件系统。这些写入是同步的并且是原子操作。通常的配
置选择是写到本地文件系统,同时写到网络文件系统。
也可以运行一个secondary namenode,它是名不符实的,和namenode并不一样。它的主
要职责是合并命名空间镜像和编辑日志以防止它变的太过巨大。secondary namenode通常
运行在一个单独的机器上,因为它需要大量的CPU以及和namode一样多的内存来执行合并。
它保存了要合并的命名空间镜像的一个副本,它可以在namenode故障时使用。尽管如此,
secondary namenode相对于namenode有延迟,所以一旦彻底故障,几乎可以肯定会有
数据丢失。这种情况下通常的做法是把网络文件系统的元数据文件拷贝到secondary namenode
上做为namenode运行(注意,可以运行一个热备份namenode来取代secondary,见
48页“HDFS高可用性“)。
查看318页“文件系统镜像及编辑日志”以了解更多。
block缓存
通常datanode从磁盘读取block,但对于经常访问的文件,它的block可能会缓存在
datanode的内存里,即非堆block cache。默认情况下,一个block只缓存在一个
datanode的内存中,尽管这个数量是可配置的。job安排者(MapReduce,Spark以及
其它一些框架)可以复用缓存的block在对应的datanode上运行task,来提高读取效率。
例如,关联中用到的一个小的表是使用缓存的一个很好的选择。
用户或应用程序通过对缓冲池添加缓冲指令来指导namenode缓存哪个文件(以及缓存
多久)。缓冲池是用来管理缓冲许可及资源使用的。
HDFS联合
namenode在内存中保存了文件系统中所有文件和block的引用,它意味着在有许
多文件的大型集群中,内存将成为规模扩大的限制(见294页“一个namenode需要
多少内存“)。HDFS联合,在2.x版本中引入,允许通过增加namenode来扩大规模,
每一个namenode管理一部分文件系统例句空间。例如,一个namenode可能管理
/user下的所有文件,另一个namenode管理/share下的所有文件。
在联合中,每一个namenode管理一个namespace volume,它由namespace的
元数据组成,以及一个block pool,它包含namespace中文件对应的所有block。
namespace volume是彼此独立的,它意味着namenode之间不会相互交互,一个
namenode失效不会影响别一个namenode管理的namespace的使用。
访问HDFS联合集群,客户端使用表来映射文件路径到namenode。这个是
使用ViewFileSystem和viewfs://URIs来配置管理的。
HDFS HA(高可用性)
结合使用namenode元数据复制到不同的文件系统及使用secondary namenode来
创建检查点来防止数据丢失并没有提供文件系统的高可用性。namenode依然是单点
失败的。如果它发生故障,所有的客户端----包括MapReduce job----也不能读取、写入
或查看文件,因为只有namenode保存了元数据以及文件到block的映射关系。在这种情况下
整个HADOOP系统都陷入瘫痪,直到一个新的namenode上线。
为了从故障中恢复,管理员要开启一个新的namenode,提供文件系统元数据复件
并配置datanode和客户端使用这个新的namenode。新的namenode不能处理请求直到:
(i)把它的namespace image加载进内存,
(ii)替换它的编辑日志,
(iii)得到足够的datanode中的block报告以结束安全模式。一个含有许多文件和
block的庞大集群,namenode启动要花费30分钟甚至更多。
恢复时间过长对于日常维护也是一个问题。事实上,namenode意料外的故障很少见,
在实践中,有针对故障停机的计划是非常重要的。
HADOOP2通过支持HDFS高可用来补救这个问题。在这个实现中,有一对处于主
备模式的namenode。一旦主namenode发生故障,备用的无缝接替它的职责继续
为客户端服务。需要改变一些架构来支持它:
- namenode必须使用高可用的共享存储来共享编辑日志。当备用namenode开启后,它读取共享的编辑日志,
使自己的状态与主namenode同步,然后继续读取主namenode写的记录。
- datanode必须同时发送报告给主备namenode,因为block映射保存在namenode的内存中,而不是磁盘上。
- 客户端必须被配置以应对namenode故障切换,使用一个对用户透明的机制来实现。
- secondary namenode的职责被包含在备份namenode中,即周期检查主namenode的namespace。
高可用共享存储有两个选择:一个是NFS filer,一个QJM(quorum journal manager)。
QJM是针对HDFS的实现,设计专门用来提供高可用编辑日志,大部分HDFS安装推荐使用它。
QJM运行像一组journal node,每一个编辑必须写到一个主journal node。典型的,有三个
journal node,所以系统可以容忍其中一个发生故障。它和zookeeper的工作方式差不多,
但是必须要清楚QJM的实现并没有使用zookeeper(然而,HDFS HA确实使用了zookeeper
来选择active namenode,在下一节会讲到)。
如果active namenode失效,standby(namenode)可以很快接管它的工作(在几十秒内)
因为在内存中有最新的状态:包括最新的编辑日志和最近的block映射。在实际中故障转移所
用时间要长一些(大约一分钟),因为系统需要小心确认active namenode是否真的发生故障了。
万一当active发生故障而standby还是关机状态时,管理员也可以开启standby。这不会比
non-HA的状况更糟,而且从可操作这个点来说它是一个进步,因为这个流程作为一个标准
操作步骤内置进了HADOOP。
Failover和fencing
active namenode过渡到standby的过程由系统中一个叫failover controller的控制器来管理。
有许多种failover controller,但是默认的实现是使用zookeeper来保证只有一个namenode是
active的。每一个namenode都运行一个轻量级的failover controller,它的工作就是监视它的
namenode是否发生故障(使用最简单的心跳机制)并且在namenode发生故障时触发failover。
failover也可以由管理员发起,例如,日常维护。这就是graceful failover,因为failover controller
管理两个namenode有序过渡来切换角色。
在ungraceful failover情况下,不能确定故障namenode是否真的停止工作了。如,
一个缓慢的网络工作可能触发failover,尽管前一个acitve namenode还在运行,并自认为还是
active namenode。HA竭尽全力确保前一个active namenode不会产生破坏----通过一个被称为
fencing的方法。
QJM在同一时刻只允许一个namenode修改编辑日志;尽管如此,前一个acitve namenode
还是有可能对客户端产生脏读,所以一个好的方法是设置一个SSH fencing命令,它会杀死
namenode进程。当使用NFS filer来共享edit log时需要更强大的fencing方法,因为它不可能
在同一时间只允许一个namenode执行写操作(这是为什么推荐使用QJM的原因)。fencing
机制包含撤消namenode访问共享存储目录(一般使用特定平台的NFS命令),以及通过远程
管理命令来禁止它的网络端口。作为最后一个手段,可以使用STONITH技术来达到fence前一个
active namenode的目的,也就是“shoot the other node in the head”,它使用一个专门的配电
装置来强制关掉主机。
客户端failover由客户端库控制。最简单的实现是使用客户端的配置文件来控制failover。
HDFS URI使用逻辑主机名称来映射到那两个namenode的地址(在配置文件中),客户端
连接每一个namenode地址直到操作成功。
以上是关于第二节 HDFS概念的主要内容,如果未能解决你的问题,请参考以下文章