(本文自动镜像于http://cloudme.net84.net/?p=27)
最近在研究分布式文件系统,HDFS由于其开源的特征以及拥有众多的使用者,成了我的首选。HDFS是Hadoopd的一个子项目,全名就叫Hadoop Distributed File System。Hadoop又是Apache基金会的一个开源项目,它依据一些公开的文档资料,克隆了Google的几大核心技术,包括MapReduce计算框架,BigTable分布式数据库(在Hadoop中叫HBase)以及Google FS(简称GFS,在Hadoop中对应的就是HDFS了)。Google虽然开源了非常多的项目,但是多局限于终端产品,比如Android,Chrome等,对于最核心的技术——服务器端的三大法宝一向是严格珍藏着,对外也就是发布了几篇论文。但是仅仅根据这几篇论文,就出来了很多模仿品,Hadoop可能是最全面最完善的一个模仿项目。我无法知道它到底能有Google的多少精髓,但是至少它受到了Yahoo!的大力支持,同时在国内也有很多主流公司在运用它(比如百度),我就不能对它小觑。
HDFS和Google FS(labs.google.com/papers/gfs-sosp2003.pdf)的实现原理几乎一样,在认为单个计算节点都不可靠的前提下,用冗余的方式来提高文件系统的可靠性。它可以搭建在廉价的PC服务器集群上,实现数以千计的结点的协同工作,提供很大的存储空间。不过,到目前为止,HDFS还只能管理同一个数据中心的电脑,无法做到跨数据中心(GFS应该可以做到了)。
HDFS不同于NFS,ext3等传统的本地文件系统,它主要负责文件数据块在网络中的派发,并不直接和磁盘打交道。所有的数据块都是以本地文件的形式保存在硬盘中的。也就是说,HDFS是架设在现有文件系统之上的分布式文件系统。考虑到性能,HDFS把文件分成很大的块(block),这个值默认是64MB。一个块就是一个本地文件,存在硬盘里面。同一文件不同的块可能位于不同的节点中,同一块也在多个节点里有备份。存放文件块的节点叫datanode。在一个HDFS集群中,有一台专门的计算机用来做namenode,主要负责处理文件的元数据,为了得知某个文件的块到底位于哪些节点,客户端必须通过namenode获取,然后才能直接和datanode通讯。因为元数据访问频繁但是数据量较小,所以namenode把这些内容全部都缓存在内存里面用来提高性能。datanode本身的冗余让单点故障在整个系统中已经不算什么问题,但是namenode容易形成单点故障,所以,HDFS又采取了一些措施来保护namenode,比如对metadata进行备份,以及增加了一个备用的namenode。
HDFS的首要目的就是为了解决搜索引擎等大型程序所需要的巨大存储量,因此,它的使用有一定的局限性。目前为止,它并不是一个通用的文件系统。它主要是针对一次写入多次读写的IO定制。允许追加写入,但是不允许随机写入。(Google FS好像允许随机写入,但是性能很低。)这种定制的IO模式能够满足搜索引擎等程序的需要,但是对于关系数据库的随机访问来说,就显得力不从心了。也许我们可以在HDFS上面增加一个逻辑层来支持随机IO,但是代价也比较大。在实际项目中,HDFS必须要和其他解决方案一起来使用,比如通过结合HBase,可以实现一个非关系数据库的大型数据存储方案。不过,也正是因为HDFS的诸多限制,让客户端不得不对IO的模式进行约束,从而大幅度提高了性能。
使用了HDFS,磁盘的利用率显然没有RAID高。HDFS通过制定复制因子,来决定数据块的复制份数。这个值默认是3。也就是说,在默认情况下,磁盘利用率只有1/3,远低于RAID5的(n-1)/n,也低于RAID10的1/2。更不用说我们设置更高的复制因子了。但是,只要不采用昂贵的SSD或者SAS盘,普通的SATA磁盘已经足够便宜,这点冗余度对于大型企业来说也不是什么问题。SATA盘容易坏也没有关系,反正Hadoop运行的前提就已经认为单个的硬件都不是可靠的。传统的RAID只能部分解决磁盘损坏的数据完整性,且在提高磁盘利用率的同时也带来了额外的性能开销,比如RAID5的写惩罚,以及在出现坏盘之后重建数据带来的性能下降等等。更重要的是,RAID只能保证硬盘出问题时的数据完整性,无法应付其他硬件(比如CPU,内存,电源等)和软件BUG带来的节点不可用等异常情况。这时,类似HDFS的这种简单复制的策略反而更可靠更高效。在复制数据块的时候,HDFS尽量让数据分散在数据中心的不同机架上,进一步提高了可靠性。如果能够跨数据中心的话,遭受导弹袭击也不用担心了!
HDFS还有很多改进的地方。由于开源的特性,加以不断改进当中,未来的前景还是很光明的。