云计算背后的秘密(2)-GFS

Sina WeiboBaiduLinkedInQQGoogle+RedditEvernote分享




由于搜索引擎需要处理海量的数据,所以Google的两位创始人Larry Page和Sergey Brin在创业初期设计一套名为“BigFiles”的文件系统,而GFS(全称为“Google File System”)这套分布式文件系统则是“BigFiles”的延续。

技术概览

首先,介绍它的架构,GFS主要分为两类节点:其一是Master节点,其主要存储与数据文件相关的元数据,而不是Chunk(数据块)。元数据包括一个能将64位标签映射到数据块的位置及其组成文件的表格,数据块副本位置和哪个进程正在读写特定的数据块等。还有Master节点会周期性地接收从每个Chunk节点来的更新(“Heart-beat”)来让元数据保持最新状态;其二是Chunk节点,它主要用于存储数据。在每个Chunk节点上,数据文件会以每个默认大小为64MB Chunk的方式存储,而且每个Chunk有唯一一个64位标签,并且每个Chunk都会在整个分布式系统被复制多次,默认次数为3。下图就是GFS的架构图:

GFS

图1. GFS的架构图

接着,在设计上,GFS主要有八个特点:

  1.  
    1. 大文件和大数据块:数据文件的大小普遍在GB级别,而且其每个数据块默认大小为64MB,这样做的好处是减少了元数据的大小,从而能使Master节点能够非常方便地将元数据都放置在内存中以提升访问效率。
    2. 操作以添加为主:文件很少会被删减或者覆盖,通常只是进行添加或者读取操作,这样能充分考虑到硬盘线性吞吐量大,但随机读写慢的特点。
    3. 支持容错:首先,虽然当时为了设计方便,采用了单Master的方案,但是整个系统会保证Master节点会有其相对应的替身(Shadow),以便于当Master节点出现问题时进行切换。其次,在Chunk层,GFS已经在设计上将节点失败视为常态,所以能非常好地处理Chunk节点失效的问题。
    4. 高吞吐量:虽然以单个节点来看,GFS的性能无论是从吞吐量还是延迟都很普通,但因为其支持上千的节点,所以总的数据吞吐量是非常惊人的。
    5. 保护数据:文件被分割成固定尺寸的数据块以便于保存,而且每个数据块都会被系统至少复制三份。
    6. 扩展能力强:因为元数据偏小,使得一个Master节点能控制和管理上千个存数据的Chunk节点。
    7. 支持压缩:对于那些稍旧的文件,可以通过对它进行压缩,来节省硬盘空间,并且压缩率非常惊人,有时甚至接近90%。
    8. 基于用户空间:GFS主要运行于系统的用户空间(User Time),虽然在效率方面,用户空间比内核空间略低,但是更便于开发和测试,还有,就是能更好利用Linux的自带的一些POSIX API。

 

优劣点

由于GFS主要是为了存储海量搜索数据而设计的,所以它在吞吐量(Throughput)和伸缩性(Scalability)这两方面表现非常优异,可谓业界的“翘楚”,但是由于其主要以64MB数据块形式存储,所以在随机访问方面速度并不优秀,虽然这点可谓是它的“软肋”,但是这本身也是其当初为了吞吐量和伸缩性所做的权衡。

相关产品

和MapReduce相似的是,GFS在开源界也有其对应的产品,最出名的是HDFS分布式文件系统,在功能和设计上,HDFS从GFS身上借鉴了很多东西,而且由于其本身就是Hadoop系列的一部分,所以它为了更好Hadoop这个MapReduce框架做了很多优化。

实际用例

现在Google内部至少运行着200多个GFS集群,最大的集群有几千台服务器,数据量是PB级别的,并且服务于多个Google服务,包括Google搜索和Google Earth等。同时,在最近几年,由于上面提到的高延迟问题,所以GFS并不很适合新的一些Google产品,比YouTube、Gmail和非常强调实时性的Caffeine搜索引擎等,所以Google已经在开发下一代GFS,代号为“Colossus”,并且在设计方面有许多不同,比如,支持分布式Master节点来提升高可用性并支撑更多文件和chunk节点能支持1MB大小的chunk以支撑低延迟应用的需要等,希望等Colossus成熟的时候,Google也能像当初GFS那样,将其设计的细节和经验拿出来和大家分享。

(3个打分, 平均:4.67 / 5)

雁过留声

“云计算背后的秘密(2)-GFS”有13个回复

  1. melon 于 2010-12-29 10:44 下午

    请问一下,为何chunk小了就可以提高随机io性能了呢?我的理解是这64MB的chunk里面会打包很多小文件,然后用一个旁路表来记录每个文件在这个chunk中的起始地址和长度,虽然简化了文件系统元数据但是依然该发生的计算还要发生,只不过简单了很多。但是如果将chunk变小比如1MB,那么势必文件系统元数据链复杂度会增加,那么依然需要耗费计算和元数据IO资源,这样的话,不知道性能提如何提升。

  2. 吴朱华 于 2010-12-29 11:49 下午

    to melon:
    具体我也不确定,因为没有披露,估计是读入到内存方便:)

  3. yunhaid 于 2011-01-02 6:25 上午

    哈,虽然对GFS没研究过,但最近写SLABFS,块大小绝对是影响性能的重要因素,块越大,外部索引越少,整体IO性能会提高,至于内部索引,只是在具体使用小文件时会使用,对整体IO影响不大。

    所以CHUNK如果从64M减少到1M,整体IO性能会大大下降。

  4. 冬瓜头 于 2011-01-02 6:50 上午

    To yunhaid:

    我理解GFS是将大量小文件打包成一段一段的chunk,然后用外部索引记录每个小文件在哪个chunk中的哪个起始地址开始的多长,通过这种方式规避传统文件系统的inode数量从而提高文件系统的查找速度和降低元数据IO量。首先想请教一下我这个理解对不对?如果确实是这样,那么我觉得无论是大文件还是小文件,其IO性能应该都是差不多的。但是根据老吴文中的介绍,降低到1MB可以降低IO延迟,这块也是我一直不理解的地方。

    To All:
    melon就是我,当时还没有注册。。

  5. 冬瓜头 于 2011-01-02 6:52 上午

    澄清一下,“那么我觉得无论是大文件还是小文件,其IO性能应该都是差不多的”,是指不会顾此失彼,不管大还是小,性能都是比较均衡的。

  6. yunhaid 于 2011-01-02 8:59 上午

    2G文件为例,64M为一个块区大小,24个索引,可以直接使用direct索引区。
    1M为一个块区,2046个索引,要使用redirect索引区。
    性能差别巨大,浪费块空间可以换取效率。

    小文件,每个1M,如果64M为一个块区,可以放64个文件,即一个大索引,64个内部索引,小文件的读取相比大文件要多一个内部索引,性能怎么可能相同?

    感觉文件系统复杂的实现在于它的目录层次结构,如果是单层次结构,类似于TAOBAO文件系统,真没什么,搞个hash索引就OK了,目录树型结构对性能的影响更大。真要追求性能,树型结构要out.

    题外话了.性能跟太多的因素相关了,磁盘的分配释放,磁盘的可用空间索引,预分配磁盘….找机会也写篇文章讲述一下slabfs的开发体会,跟大家交流,最近在玩fpga,在想另一个思路,硬件加速能否用在FS上?!

  7. 冬瓜头 于 2011-01-02 6:50 下午

    小文件肯定性能要差,只是说GFS这种做法相比传统文件系统来讲处理小文件效率来讲是高多了,所以说大小文件时比较均衡的,不会顾此失彼。但是不明白为何下一代他要换成1M的块,1M相对于64M来讲,索引数量可以近似认为相等,可能真如老吴所说,与内存管理、预读之类有关了,单从磁盘上的数据排布来讲真看不出有什么提升。

    TFS2.0是否已经出来了?yunhaid是否已经看过TFS源代码了啊?请教一下,单层结构与树形结构比较,各优缺点是什么,如果说单层结构效率高于树形,那么必定有劣势,比如是否可扩展性差?

    用FPGA加速文件系统处理相比通用CPU来讲效率会提升很高么?我觉得文件系统瓶颈还是在元数据设计和IO而不是计算,另外如果用FPGA的话,功耗是个问题,流片到ASIC的话,那不利于后续逻辑的升级,感觉是个大胆的想法,但是商用化的话还不靠谱吧。。

  8. yunhaid 于 2011-01-03 3:45 上午

    没研究过TFS,只看过tfs的实现简介,主要研究的对象是ZFS,然后参考了btrfs,ext4。树型目录的实现,是一种层次嵌套的递归,简言之就是redirect 再redirect,每个目录内都会有一个avl平衡树索引文件名,目录层次越深,树索引越多。如果是单层文件系统,只需要一个avl平衡树索引就够了,性能相比很明显。

    提一点,磁盘空间的连续预读实现,对性能会有极大提高。ext4里就有对此专门的优化。我也实现了一套slab_disk_alloc,单此一项就有了10%的性能提高。呵,slab的核心思想也在于此.

    文件系统的最大瓶颈就是硬盘的IO读写了,cache可以缓解IO,但是不足也很明显,数据不同步问题…

    硬件FS只是想法,因为对fpga还在学习阶段,所以也没想明白…

  9. 冬瓜头 于 2011-01-03 5:52 上午

    受教。那请问为何不一开始都是用单层结构呢?还有关于预读,能否介绍一下slab_disk_alloc的预读算法为何会强于之前的算法?不知道这套预读算法对随机IO是否提升明显?

  10. 吴朱华 于 2011-01-03 8:52 上午

    支持你们的讨论,让我收益非浅

  11. yunhaid 于 2011-01-03 6:18 下午

    目录文件的层次实现(ZFS 是内存AVL, 磁盘采用结构链表,我开发的slabfs采用磁盘avl树)

    directory1 —|AVL TREE|– file1
    — file2
    — file3
    — file4
    — …..
    — directory2 —|AVL TREE| — file5
    — file6
    — file7
    — file8
    — …..

    无目录文件的实现(TFS)

    directory1 —|AVL TREE|– file1
    — file2
    — file3
    — file4
    — …..

    目录文件无层次实现(BTRFS采用B+)
    directory1 —|AVL TREE|– file1
    — file2
    — file3
    — file4
    — …..
    — directory2/file5
    — directory2/file6
    — directory2/file7
    — directory2/file8

    论效率,无层次实现及无目录文件实现,效率最高,最简单。不足是没有层次结构,单一节点损坏会影响全局,这也是btrfs最大的心病,文件系统的第一要素是存储完整性。
    层次实现也是目前通常的文件系统实现方式。

    slab_disk_alloc是磁盘空间的分配实现,简单说就是磁盘块预分配(上面笔误写成预读),简单说就是一个磁盘块池,其中的磁盘块已经预先分配好,即时按需使用,跟slab内存池是相同的实现。

    预读对于随机IO的性能没有任何帮助,相反还会起反作用。对于随机IO而言,磁盘块的分配更重要,使文件尽量是连续的磁盘块,会对IO有决定性的影响,嗯,这个点是关键点.

  12. YAcc 于 2011-01-03 8:13 下午

    Quinlan作为GFS tech leader,对GFS进化大致是这样说的,2003年的数据量TB级,2006年就变成PB级,现在数据中心是EB级的,变化难以预料,从设计上来考虑,64M粒度能做到的事,1M粒度也能做到,还能做的更多,这可能是长远考虑吧(Quinlan原话My gut feeling is that if you design for an average 1-MB file size, then that should provide for a much larger class of things than does a design that assumes a 64-MB average file size. ),加之所有google的application都跑在GFS上,所以设计考虑的比较多。
    Quinlan访谈连接http://queue.acm.org/detail.cfm?id=1594206

  13. 冬瓜头 于 2011-01-03 8:21 下午

    谢谢yunhaid提供细节信息。说道文件-块对应的策略和算法,如果要实现很高的随机IO效果的话,那么需要将一个文件尽量分散在所有底层存储单元上从而尽量利用资源。但是这么做又有一个反作用,就是当大块连续地址IO的时候,一个IO就有可能占用所有底层资源,所以此时,每个节点上分配的空间颗粒粒度就是关键问题了,我的设想中,一个文件系统应当具有让用户来选择不同分配方式的能力,甚至应该具有分配方式后台自动透明变迁的能力。