Hadoop学习笔记(五):一些关于HDFS的基本知识
当某个数据集大大小超出单个物理机的存储能力时,我们可以考虑使用集群。管理跨网络机器存储的文件系统叫做分布式文件系统(Distributed FileSystem)。随着多节点的引入,相应的问题也就出现了,例如其中最重要的一个问题就是如何保证在某个节点失败的情况下数据不会丢失。Hadoop中有一个核心子项目HDFS(Hadoop Distributed FileSystem)就是用来管理集群的存储问题的,当然在Hadoop中不仅仅只能使用HDFS,Hadoop中有一个通用的抽象的文件系统概念,这样可以使Hadoop在不同种类的文件系统下运作,例如Hadoop可以与Amazon的S3文件系统集成起来一起使用。
HDFS的设计理念
1、存储超大文件
这里的“超大文件”是指几百MB、GB甚至TB级别的文件。
2、流式数据访问
HDFS是建立在最有效的数据处理模式是一次写多次读(write-once,read-many-times)的模式的概念之上的,HDFS存储的数据集作为hadoop的分析对象。在数据集生成后,长时间在此数据集上进行各种分析。每次分析都将设计该数据集的大部分数据甚至全部数据,因此读取整个数据集的时间延迟比读取第一条记录的时间延迟更重要。(流式读取最小化了硬盘的寻址开销,只需要寻址一次,然后就一直读啊读。硬盘的物理构造导致寻址开销的优化跟不上读取开销。所以流式读取更加适合硬盘的本身特性。当然大文件的特点也更适合流式读取。与流数据访问对应的是随机数据访问,它要求定位、查询或修改数据的延迟较小,比较适合于创建数据后再多次读写的情况,传统关系型数据库很符合这一点)
3、运行在普通廉价的服务器上HDFS设计理念之一就是让它能运行在普通的硬件之上,即便硬件出现故障,也可以通过容错策略来保证数据的高可用。
HDFS的不便之处
1、将HDFS用于对数据访问要求低延迟的场景
由于HDFS是为高数据吞吐量应用而设计的,必然以高延迟为代价。
2、存储大量小文件
HDFS中元数据(文件的基本信息)存储在namenode的内存中,而namenode为单点,小文件数量大到一定程度,namenode内存就吃不消了。
HDFS中的基本概念
1.Blocks
每个磁盘都有一个数据块大小(block size),这是一次可以读取或写入数据的最小单位。HDFS中也有数据块的概念,不过HDFS中的数据块却比一般磁盘的数据块(一般为512Byte)大得多。像普通磁盘文件系统那样,HDFS把文件分割成block(下文如果没有特别声明,block都是指HDFS中的64MB大小的block)大小的数据块,并独立存储起来。不过与普通磁盘文件系统不同的是,如果一个文件比单个block小,这个文件并不会整个block(如果一个几百kb的小文件占用了整个64MB大小的数据块,那该造成多大的浪费啊)。
HDFS为什么要使用大数据块 HDFS中的数据块比普通磁盘文件系统要大得多,这么做的原因是最小化文件系统中数据寻址的时间。通过设置一个较大的block大小,寻址数据的时间就会比传输数据的时间小得多,从而处理一个大文件(HDFS主要用来处理大数据的嘛)的时间就主要决定于数据传输的时间了。 |
在分布式文件系统层面又抽象出一个block的概念可以带来有以下好处:
1. 由于没有一个文件必须存储在单个磁盘上的要求了,从而单个文件可以比集群中的任何一个节点的存储空间还要大,这样可以充分利用集群的存储能力。有可能(虽然不常见)一个文件会占用整个集群上所有节点的存储空间。
2. 以block(而不是文件)作为抽象单元简化了存储子系统。简单是所有存储系统的共同目标,在发生故障方式多种多样的分布式文件系统中尤为重要。存储子系统只需要处理block就可以了,从而简化了存储管理(因为block是固定大小的,可以很容易的计算出某个磁盘最多可以存储多少个block),而且还省去了元数据的管理负担(因为block只是需要存储的一串数据,文件的诸如访问权限之类的元数据不需要同block存储在一起,从而可以通过另一个系统namenode单独管理起来)。
3. 有了block,提供数据容错和可用性的冗余备份(replication)机制可以更好的工作。在HDFS中,为了防止数据块损坏,或者磁盘及机器当机,每一个block在不同机器上都有几份备份(默认为3)。如果一个block不能用了,HDFS会以一种对用户透明的方式拷贝一份新的备份出来,从而把集群的数据安全级别恢复到以前的水平(你也可以通过提高冗余备份数来提高数据的安全级别)。
可以使用HDFS中的fsck命令在block层面交互,例如运行命令:
% hadoop fsck / -files -blocks
会列出文件系统中组成所有文件的blocks。
2. NameNode和DataNode
HDFS集群中有两种节点:NameNode和DataNode。NameNode管理整个文件系统的命名空间(namespace),它维护着整个文件系统树以及树中所有文件及目录的元数据。这些信息在本地文件系统中以两种形式永久保存:namespace image(包括namespace中所有文件的inode和block列表)和edit log(记录了所有用户对HDFS所做的更改操作)。NameNode也保存着构成给定文件的blocks的位置,但这些信息并不是永久保存在磁盘中的,因为这些信息是在系统启动时根据datanode的反馈信息重建、并且是定时基于datanode的报考更新的,具有很强的动态性。
客户端(client)代表用户(user)通过与NameNode和DataNode交互来访问文件系统。client提供了一个类似POSIX(Portable Operating System Interface)的文件系统接口,所以用户在编程中并不需要namenode和datanode的具体实现。
namenode是整个分布式文件系统的一个单点故障(single point of failure),没有了namenode整个分布式文件系统就无法使用了,因为我们无法从blocks中重构出相应的文件了。所以确保namenode能从失败中及时恢复是很重要的一件事,我们可以从以下两方面入手:
1. 第一种方法就是备份namenode中保存的永久信息(也就是上文中所提到的namespace image和edit log),namenode可以经过额外配置把它的永久信息保存到多个文件系统上去(这些多写操作是同步和原子性的)。最常用的做法是把永久信息保存到本地文件系统和某个远程NFS(Network FileSystem)上去。
2. 另一种可能的做法就是运行一个secondary namenode,尽管它的名字跟namenode听起来差不多,但它的功能跟namenode却不一样。它最主要的工作就是把namespace image检查点文件与edit log相融合(以防止edit log过大)并把融合后的namespace image保存在自己的本地文件系统上,同时发送这个新的备份给namenode。因为需要大量CPU资源和跟namenode一样大小内存的缘故, secondary namenode通常运行在另一个单独的机器上(关于更多secondary namenode运行的描述请参看这里)。然后由于secondary namenode上保存的状态信息总是要滞后于namenode上的状态信息的缘故(未融合的edit log记录了这一部分改变),如果namenode完全失败,数据肯定要丢失一部分。
通常的做法是把上述两种方法结合起来,也即当namenode当机时,把远端NFS上的namespace image拷贝到secondary namenode上,然后把secondary namenode当做namenode来运行。
3. Hadoop Fedoration
namenode在内存中保存着文件系统中每个文件和目录的引用,但集群规模扩大时,这便造成了一个瓶颈。于是在hadoop 2.x发行版中引入了一个新的概念:Hadoop Fedoration。它允许集群拥有不止一个namenode,这样每个namenode只负责维护文件系统中的一部分,例如一个namenode维护/user目录,另一个namenode可以维护/share目录。
在fedoration中,每个namenode维护两部分信息:1)由namespace 元数据组成的namespace volume;2)包含其负责维护的某一部分文件系统中的的所有文件的block位置信息的block pool。namespace volume各自之间是独立的,这就意味着namenode之间不用交互,而且某个namenode当机并不影响其他namenode的正常使用。相对于namespace volume而言,Block pool并不是分区的,所以datanodes需要向集群中的每个namenode注册,并且可能要存储来自多个block pool的数据。
要想使用带有fedoration特性的cluster,用户可以使用用户端的挂载表来映射文件路径到namenode。这个可以通过ViewFileSystem来配置,并使用viewfs:// URI.
(关于更多Hadoop Fedoration的内容请参看这里)
4. HDFS High-Availabilty
虽然通过在多个文件系统备份namespace metadata和使用secondary namenode来定期合并namespace image和edit log以产生新的checkpoint可以保护集群以免数据丢失。但这并没有提供集群的高可用性,因为namenode本身仍然是一个单点故障——如果namenode当掉了,所有的客户端,包括mapreduce作业都无法正常读、写以及查看文件了,因为namenode是维护namespace metadata和提供file-to-block映射的唯一库。
要想从失败的namenode中恢复,管理员应启动一个新的namenode,同时配置datanode和用户使用这个新的namenode。这个新的namenode暂时还不能正常运作,直到它做完了以下几件事:
1) 把namespace image备份加载入内存;
2) 重放edit log中的操作;
3) 从datanode中接受足够的block report(也就是记录各个datanode中block的信息以确定file-to-block映射),然后离开safe mode。
在有很多节点和文件的大的集群中,这个操作可能要花费几十分钟的时间!!
Hadoop 2.x发行版通过加入对HDFS High-Availabilty的支持而有效避免了长时间的downtime。在这种实现中,有一对namenode,它们分别配置为active和standby。当active namenode当掉时,standby namenode立即接手继续为client提供服务,期间的中断时间很小。为了实现HDFS High-Availabilty,结构上发生了以下变化:
1) 两个namenode使用一个高可用的共享设备(最初HA实现使用的是NFS来共享edit log,不过在未来的版本中会提供更多的选项,如构建于ZooKeeper之上的基于BookKeeper的系统)来存储edit log,当standby namenode接手运行时,它就会立即重放edit log中的操作(同时它也充当着secondary namenode的角色,不停地合并老的namespace image和新的edit log以免edit log过大),从而很快达到与active namenode当掉前的状态。
2) datanode需要向两个namenode发送block report,因为block mapping是存放在内存,而不是磁盘中的。
3) 用户端(client)必须被合适配置并采用一种对用户透明的方式处理namenode的失败恢复。综合起来,如下图所示:
edit log中都保存着哪些信息? All mutations to the file system namespace, such as file renames, permission changes, file creations, block allocations, etc, are written to a persistent write-ahead log by the Name Node before returning success to a client call. In addition to this edit log, periodic checkpoints of the file system, called the fsimage, are also created and stored on-disk on the Name Node. Block locations, on the other hand, are stored only in memory. The locations of all blocks are received via “block reports” sent from the Data Nodes when the Name Node is started. |
有了以上改变做基础,当active namenode当掉时,因为standy namenode保存着最新的edit log(同时还有上个检查点镜像文件)和最新的block mapping,standy namenode可以在几十秒内很快地接手继续工作。在实际应用中测得的失败恢复时间会长一些(大约一分钟左右),因为系统需要额外的时间确定active namenode确实已经当机了。
转载请注明出处:http://www.cnblogs.com/beanmoon/archive/2012/12/08/2809315.html
作者:beanmoon
出处:http://www.cnblogs.com/beanmoon/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
该文章也同时发布在我的独立博客中-豆月博客。