Google 分布式系统三大论文(一)The Google File System

The Google File System 中文版

摘要

我们设计并实现了Google文件系统,一个面向分布式数据密集型应用的、可伸缩的分布式文件系统。虽然运行在廉价的日用硬件设备上,但是它依然了提供容错功能,为大量客户机提供了很高的总体性能。

虽然与很多之前的分布式文件系统有很多相同目标,但是,我们的设计已经受应用的负载情况和技术环境影响,现在以及可预见的将来都反映出,我们的设计和早期的分布式文件系统的设想有了显著的分离。这让我们重新审视了传统文件系统在设计上的选择,探索彻底不同的设计点。

GFS成功满足了我们的存储需求。其作为存储平台被广泛的部署在Google内部,该平台用来产生和处理数据,这些数据被我们的服务以及需要大规模数据集的研究和开发工作使用。迄今为止,最大的一个集群利用一千多台机器上的数千个硬盘,提供数百TB的存储空间,同时被数百个客户机访问。

在本论文中,我们展示了设计用来支持分布式应用的文件系统接口的扩展,讨论我们设计的许多方面,最后对小规模基准测试和真实使用作了测量报告。

常用术语

设计,可靠性,性能,测量

关键词

容错,可伸缩性,数据存储,集群存储

1.     简介

为了满足Google迅速增长的数据处理需求,我们设计并实现了Google文件系统(Google File SystemGFS)GFS与之前的分布式文件系统有着很多相同的目标,比如,性能、扩展性、可靠性以及可用性。但是,我们的设计还受对我们的应用的负载和技术环境的观察的影响,现在以及可预见的将来都反映出,我们的设计和早期的分布式文件系统的设想有了显著的分离。这让我们重新审视了传统文件系统在设计上的选择,在设计上探索了彻底不同的设计点。

首先,组件失效被认为是常态事件,而不是意外事件。文件系统由几百乃至数千台由廉价的日常部件组装成的存储机器组成,同时被相当数量的客户机访问。部件的数量和质量事实保证了任意给定时间,一些部件无法工作,一些部件无法从它们目前的失效状态中恢复。我们遇到过如下原因导致的问题,比如应用程序bug、操作系统的bug、人为失误,甚至还有硬盘、内存、连接器、网络以及电源失效。因此,持久的监控、错误侦测、容错以及自动恢复必须集成在系统中。

其次,以传统的标准衡量,我们的文件非常巨大。数GB的文件非常普遍。每个文件通常包含许多应用程序对象,比如web文档。当我们定期由数亿个对象构成的快速增长的数TB的数据集时,即使文件系统支持,管理数十亿KB大小的小文件也是不实用的。因此,设计的假设条件和参数,比如I/O 操作和Block的尺寸都不得不重新考虑。

第三,绝大部分文件的变更是采用在追加新数据,而不是重写原有数据的方式。文件内部的随机写在实际中几乎不存在。一旦写完之后,文件只能读,而且通常只能顺序读。各种数据符合这些特性,比如:一些可能组成了数据分析程序扫描的超大数据集;一些可能是正在运行的应用程序生成的连续数据流;一些可能是档案数据;一些可能是由一台机器生成、另外一台机器处理的中间数据,同时处理或者稍后适时处理。考虑到这种针对海量文件的访问模式,数据的追加是性能优化和原子性保证的焦点所在,客户端对数据块缓存毫无吸引力。

第四,通过增加灵活性,应用程序和文件系统API的协同设计对整个系统有益。比如,我们放松了对GFS一致性模型的要求,不用在应用程序中强加繁重负担,大大简化了文件系统。我们甚至引入了原子性的追加操作,这样多个客户端可以对一个文件同时进行追加操作,不需要他俩之间额外的同步机制。这些问题会在下文进行详细讨论。

当前针对不同目的部署了多重GFS集群。最大的一个集群拥有超过1000个存储节点,超过300TB的硬盘存储,被不同机器上的数百个客户端连续不断的频繁访问。

2.设计概述

2.1 假设

在设计满足我们需求的文件系统时候,我们被这种现实指引着:我们的假设既有机遇、又有挑战。我们之前提到一些关键关注点,现在更详细地展示我们的假设。

系统由许多廉价的日用组件组成,组件失效是一种常态。系统必须持续监控自身状态,探测,处理容错并且迅速地恢复失效的组件。

系统存储一定数量的大文件。我们预期会有几百万个文件,文件的大小通常在100MB或者以上。数个GB大小的文件也是普遍存在,并且应该被被有效的管理。系统也必须支持小文件,但是不需要针对小文件做优化。

系统的工作负载主要由两种读操作组成:大规模的流式读取和小规模的随机读取。大规模的流式读取中,单次操作通常读取数百KB的数据,更常见的是一次读取1MB甚至更多的数据。来自同一个客户机的连续操作通常是读取一个文件中一个连续区域。小规模的随机读取通常是在任意位移上读取几个KB数据。对性能敏感的应用程序通常把小规模的随机读取分批处理并排序,如此在文件中稳固前进而不是往复来去。

系统的工作负载还包括许多大规模的、顺序的、对文件追加数据的写操作。通常操作的大小和读操作类似。数据一旦被写入后,文件很少被再次变更。系统支持在文件任意位置写入的小型操作,但是这种操作不必高效。

系统必须高效的、定义明确的(alex注:well-defined)实现多客户端并行追加数据到同一个文件里的语意。我们的文件通常作为“生产者-消费者”队列,或者为多路合并使用。数百个生产者,每台机器上运行一个,并发地对一个文件进行追加。最小同步开销原子性是必要的。文件可以在稍后读取,或者是消费者在追加同时读取文件。

高可持续的网络带宽比低延迟更重要。我们的大多数目标程序很看重高速率大批量地处理数据,极少有程序对单一的读写操作有严格的响应时间要求。

2.2 接口

GFS 提供了一套常见的文件系统接口,尽管它没有实现像POSIX的一套标准API。文件以目录的形式分层组织,用路径名标识。我们支持常用的操作,如创建、删除、打开、关闭、读写文件。

另外,GFS 有快照和记录追加操作。快照以很低的成本创建一个文件或者目录树的拷贝。记录追加操作允许多个客户端同时对一个文件进行追加,同时保证每个单一客户端追加的原子性。多个客户端可以在不需要额外锁的情况下,同时追加数据,这对于实现多路结果合并,以及”生产者-消费者”队列非常有用。我们发现这些类型的文件对于构建大型分布应用是非常重要的。快照和记录追加操作将在3.43.3节分别作进一步讨论。

2.3 架构

一个GFS 集群包含一个单独的masteralex注:这里的一个单独的master节点的含义是GFS系统中只存在一个逻辑上的master组件。后面我们还会提到master节点复制,因此,为了理解方便,我们把master节点视为一个逻辑上的概念,一个逻辑的master节点包括两台物理主机,即两台master服务器)和多台chunkserver,并且被多个客户端访问,如图所示。其中的每台机器通常都是运行着用户级别(user-level)的服务器进程的日常Linux机器。我们可以很容易地把chunk服务器和客户端都运行在同一台机器上,前提是机器资源允许,并且运行古怪应用程序代码而引起的不可靠性是可以接受的。

文件都被分割成固定大小的块。在创建块的时候,master会对每个块分配一个不可变的、全球唯一的64位的块句柄来进行标识。Chunkserver将块作为linux 文件保存在本地硬盘上,并且根据指定的块句柄和字节范围来读写块数据。为了可靠,每个块都会复制到多个chunkserver上。缺省情况下,我们存储三个副本,不过用户可以为不同的文件命名空间区域指定不同的复制级别。

Master维护所有的文件系统元数据。这些元数据包括命名空间、访问控制信息、文件到块的映射信息、以及当前块的位置。Master节点还控制着系统范围内的活动,比如,块租用管理(alex注:BDB也有关于lease的描述,不知道是否相同、孤立块的垃圾回收、以及块在Chunkserver间的迁移。Master用心跳信息周期地和每个Chunkserver通讯,向Chunkserver发送指令并收集其状态。

链接到每个应用程序里的GFS客户端代码实现了文件系统API,代表应用程序与masterChunkserver通讯以及读写数据。客户端和master交互元数据操作,但是所有承载数据的通信都是直接和Chunkserver进行的。我们不提供POSIX标准的API,因此不需要在Linux vnode层建立钩子程序。

无论是客户端还是Chunkserver都不需要缓存文件数据。客户端缓存收效甚微,因为大多数程序要么流式处理一个巨大文件,要么工作集太大根本无法缓存。通过消除缓存相关的问题简化了客户端和整个系统。(然而,客户端会缓存元数据。)Chunkserver不需要缓存文件数据的原因是,数据块以本地文件的方式保存,Linux 缓冲区已经把经常访问的数据缓存在了内存中。

2.4 单一Master节点

单一的master节点极大地简化了我们的设计。并且使master可以使用全局信息(knowledge)进行复杂的块部署和副本决策。然而,我们必须使其与读写的相关性降到最小,以避免其成为瓶颈。客户端绝不通过master读写文件数据。相反,客户端询问master它应该联系哪一个Chunkserver。客户端将这些信息缓存有限的时间,后续的操作直接和Chunkserver进行交互。

我们参考图1解释一次简单读取交互。首先,客户端使用固定的块大小将应用程序指定的文件名和字节偏移转换成文件中的块索引。然后,它将包含文件名和块索引的请求发给masterMaster回复相应的块句柄和副本位置信息。客户端使用文件名和Chunk索引作为键缓存这些信息。

之后客户端发送请求到其中的一个副本处,一般是最近的。请求信息指定了Chunk句柄和块内字节范围。对同一个块的进一步读取不再需要客户端和master的交互了,知道缓存信息过期或者文件被重新打开。实际上,客户端通常会在一次请求中请求多个块,master也可能立刻包含了那些请求之后的块信息。这些额外的信息在实际上没有任何额外代价的情况下,回避了客户端和master未来一些可能的交互。

2.5 Chunk尺寸

块的大小是关键的设计参数之一。我们选择了64MB,这个尺寸远远大于通常文件系统的块大小。每个块副本都以普通Linux文件的形式保存在Chunkserver上,只有在需要的时候才扩大。惰性空间分配策略避免了由于内部碎片导致的空间浪费,也许这是对这么大的块尺寸最有争议的地方。

大尺寸块有几个重要的优势。首先,它减少了客户端和master交互的需求,因为对同一块的读写只需要一次和mater的初始请求来获取块的位置信息。这种缩减我们的工作负载至关重要,因为应用程序大都是连续读写大文件。即使是小规模的随机读取,客户端可以轻松地为一个数TB的工作集缓存所有的块位置信息。其次,因为采用较大块,客户端很可能对一个块执行多次操作,这样可以通过与Chunkserver在很长的时间内保持持久的TCP 连接来减少网络负载。再者,它减少了在master上保存的元数据的大小。这就允许我们把元数据保存在内存中,这也带来了其它优势,我们将在在2.6.1节进行讨论。

另一方面,即使配合惰性空间分配,大尺寸块也有其缺点。小文件包含少量的块,甚至只有一个块。如果许多客户端访问同一个小文件,存储这些块的Chunkserver就会变成热点。在实际中,由于我们的程序通常是连续的读取包含多个块的大文件,热点还不是主要问题。

然而,当GFS第一次被批处理队列系统使用的时候,热点问题还是显露了:一个可执行文件作为一个单块文件写在了GFS上,之后同时在数百台机器上启动。存放这个可执行文件的几个Chunkserver被数百个并发请求造成过载。我们通过使用更大的复制因子来保存这样的可执行文件,并且让批处理队列系统错开程序的启动时间的方法解决了这个问题。一个可能的长效解决方案是,在这种的情况下允许客户端从其它客户端读取数据(p2p?)。

2.6 元数据

Masteralex注:注意逻辑的master节点和物理的master服务器的区别。后续我们谈的是每个master服务器的行为,如存储、内存等等,因此我们将全部使用物理名称)存储3种主要类型的元数据:文件和块的命名空间、文件到块k的映射、每个块副本的位置。所有的元数据都保存在master的内存中。前两种类型(命名空间、文件到块的映射)同时也会通过记录变更到操作日志的方式持久存储,该日志存储在master的本地磁盘上,并且在远程机器上备份。使用日志使我们能够简单可靠地更新master的状态,并且不用冒着万一master崩溃数据不一致的风险。Master不会持久存储块位置信息。相反,Master会在启动,或者有新的Chunkserver加入集群时,向各个Chunkserver询问它们的块信息。

2.6.1 内存中的数据结构

因为元数据保存在内存中,master的操作非常快。并且,Master在后台周期性扫描自己的整个状态简单高效。这种周期性的扫描用于实现块垃圾收集、在Chunkserver失效时重新备份、通过块迁移来均衡跨Chunkserver的负载及磁盘使用状况。4.34.4章节将进一步讨论这些行为。

对于这种memory-only式的方法的一个潜在担心在于:块的数量亦即整个系统的容量受限于master所拥有的内存大小。这在实际应用中并不是一个严重的限制。Master为每个64M数据块维护少于64个字节的元数据就。由于大多数文件包含多个块,因此大多数块是满的,除了最后一个块是部分填充的。同样,每个文件需要的文件命名空间数据通常少于64字节,因为它使用前缀压缩紧密地存储文件名字。

如果有必要支持更大的文件系统,相比于通过在内存中存储元数据而获得的简洁性、可靠性、高性能和灵活性而言,为master增加额外内存的费用也是很少的。

2.6.2 Chunk 位置信息

Master不保存哪个Chunkserver拥有指定块的副本的持久化记录。Master只是在启动的时候轮询Chunkserver以获取那些信息。Master可以保持自己是最新的(thereafter),因为它控制了所有的块的部署,而且通过定期心跳信息监控Chunkserver的状态。

我们最初试图把块的位置信息持久地保存在master上,但是我们认定在启动的时候从Chunkserver请求数据,之后定期轮询更简单。这样消除了在Chunkserver加入、离开集群、更名、失效、以及重启等情况发生的时候,保持masterChunkserver同步的问题。在一个拥有数百台服务器的集群中,这类事件会频繁的发生。

理解这个设计决策的另外一种方式就是认识到:对于块是否在它的硬盘上,Chunkserver才说了算。试图在master上维护一个这些信息的一致视图是毫无意义的,因

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值