Google(一)——GFS

来源:互联网 发布:pc网络竞技游戏 编辑:程序博客网 时间:2024/06/18 14:27

设计目标: 性能、可伸缩性、可靠性以及可用性(传统目标);针对google应用提出的目标:

1.      组件失效被认为是常态事件,而不是意外事件;

2.      以通常的标准衡量,我们的文件非常巨大;(也会处理小文件,但是不需要对小文件做专门的优化)

3.      绝大部分文件的修改是采用在文件尾部追加数据,而不是覆盖原有数据的方式;

4.      应用程序和文件系统API的协同设计提高了整个系统的灵活性。

GFS提供了快照和记录追加操作。

Ø  架构

         一个GFS集群包含一个单独的Master节点)、多台Chunk服务器,并且同时被多个客户端访问。无论是客户端还是Chunk服务器都不需要缓存文件数据。客户端缓存数据几乎没有什么用处,因为大部分程序要么以流的方式读取一个巨大文件;Chunk服务器不需要缓存 文件数据的原因是,Chunk以本地文件的方式保存,Linux操作系统的文件系统缓存会把经常访问的数据缓存在内存中。

         GFS存储的文件都被分割成固定大小的Chunk。在Chunk创建的时候,Master服务器会给每个Chunk分配一个不变的、全球唯一的 64位的Chunk标识。Chunk服务器把Chunk以linux文件的形式保存在本地硬盘上,并且根据指定的Chunk标识和字节范围来读写块数据。 出于可靠性的考虑,每个块都会复制到多个块服务器上。缺省情况下,我们使用3个存储复制节点,不过用户可以为不同的文件命名空间设定不同的复制级别。

         Master节点管理所有的文件系统元数据。这些元数据包括名字空间、访问控制信息、文件和Chunk的映射信息、以及当前Chunk的位置信息。Master节点还管理着系统范围内的活动,比如,Chunk租用管理、孤儿Chunk(alex注:orphanedchunks)的回收、以及 Chunk在Chunk服务器之间的迁移。Master节点使用心跳信息周期地和每个Chunk服务器通讯,发送指令到各个Chunk服务器并接收 Chunk服务器的状态信息

Ø  Master

如上图,gfs读取文件的流程为:

1.      客户端把文件名和程序指定的字节偏移,根据固定的Chunk大小,转换成文件的Chunk索引。

2.      它把文件名和Chunk索引发送给Master节点。Master节点将相应的Chunk标识和副本的位置信息发还给客户端。

3.      客户端用文件名和 Chunk索引作为key缓存这些信息。

4.      客户端发送请求到其中的一个副本处,一般会选择最近的。请求信息包含了Chunk的标识和字节范围。

5.      在对这个Chunk的后续读取操作中,客户端不必再和Master节点通讯了,除非缓存的元数据信息过期或者文件被重新打开。实际上,客户端通常会在一次请求中查询多个Chunk信息,Master节点的回应也可能包含了紧跟着这些被请求的Chunk后面的Chunk的信息

Master服务器存储3种主要类型的元数据:文件和Chunk的命名空间、文件和Chunk的对应关系、每个Chunk副本的存放地点。所有的元数据都保存在 Master服务器的内存中。前两种类型的元数据(命名空间、文件和Chunk的对应关系)同时也会以记录变更日志的方式记录在操作系统的系统日志文件中,日志文件存储在本地磁盘上,同时日志会被复制到其它的远程Master服务器上。Master服务器不会持久保存Chunk位置信息。Master服务器在启动时,或者有新的Chunk服务器加入时,向各个Chunk服务器轮询它们所存储的Chunk的信息,之后定期轮询更新。这种设计简化了在有Chunk服务器加入集群、离开集群、更名、失效、以及重启的时候,Master服务器和Chunk服务器数据同步的问题。Master服务器不需要维护一个全局的视图信息。

我们会把日志复制到多台远程机器,并且只有把相应的日志记录写入到本地以及远程机器的硬盘后,才会响应客户端的操作请求。Master服务器会收集多个日志记录后批量处理,以减少写入磁盘和复制对系统整体性能的影响。Master 服务器在日志增长到一定量时对系统状态做一次Checkpoint。将所有的状态数据写入一个Checkpoint文件(alex注:并删除之前的日志文件)。在灾难恢复的时候,Master服务器就通过从磁盘上读取这个Checkpoint文件,以及重演Checkpoint之后的有限个日志文件就能够恢复系统。Checkpoint文件以压缩B-树形势的数据结构存储,可以直接映射到内存,在用于命名空间查询时无需额外的解析。

Ø  Chunk

Chunk的大小是关键的设计参数之一。我们选择了64MB,这个尺寸远远大于一般文件系统的Block size。每个Chunk的副本都以普通Linux文件的形式保存在Chunk服务器上,只有在需要的时候才扩大。选取大chuck size的原因:

1.      它减少了客户端和Master节点通讯的需求,因为只需要一次和Mater节点的通 信就可以获取Chunk的位置信息,之后就可以对同一个Chunk进行多次的读写操作

2.      采用较大的Chunk尺寸,客户端能够对一个块进行多次操作,这样就可以通过与Chunk服务器保持较长时间的TCP连接来减少网络负载

3.      选用较大的Chunk尺寸减少了Master节点需要保存的元数据的数量。这就允许我们把元数据全部放在内存中

另一方面,即使配合惰性空间分配,采用较大的Chunk尺寸也有其缺陷。小文件包含较少的Chunk,甚至只有一个Chunk。当有许多的客户端对同一个小文件进行多次的访问时,存储这些Chunk的Chunk服务器就会变成热点。我们通过使用更大的复制参数来保存可执行文件,以及错开批处理队列系统程序的启动时间的方法解决了这个问题。一个可能的长效解决方案是,在这种的情况下,允许客户端从其它客户端读取数据。

Ø  系统交互

使用租约 (lease)机制来保持多个副本间变更顺序的一致性。Master节点为Chunk的一个副本建立一个租约,我们把这个副本叫做主Chunk。主 Chunk对Chunk的所有更改操作进行序列化。所有的副本都遵从这个序列进行修改操作。因此,修改操作全局的顺序首先由Master节点选择的租约的 顺序决定,然后由租约中主Chunk分配的序列号决定。即使 Master节点和主Chunk失去联系,它仍然可以安全地在旧的租约到期后和另外一个Chunk副本签订新的租约。

 

1.      客户机向Master节点询问哪一个Chunk服务器持有当前的租约,以及其它副本的位置。如果没有一个Chunk持有租约,Master节点就选择其中一个副本建立一个租约(这个步骤在图上没有显示)。

2.      Master节点将主Chunk的标识符以及其它副本(又称为secondary副本、二级副本)的位置返回给客户机。客户机缓存这些数据以便后续的操作。只有在主Chunk不可用,或者主Chunk回复信息表明它已不再持有租约的时候,客户机才需要重新跟Master节点联系。

3.      客户机把数据推送到所有的副本上。客户机可以以任意的顺序推送数据。Chunk服务器接收到数据并保存在它的内部LRU缓存中,一直到数据被使用或者过期交换出去。由于数据流的网络传输负载非常高,通过分离数据流和控制流,我们可以基于网络拓扑情况对数据流进行规划,提高系统性能,而不用去理会哪个Chunk服务器保存了主Chunk。

4.      当所有的副本都确认接收到了数据,客户机发送写请求到主Chunk服务器。这个请求标识了早前推送到所有副本的数据。主Chunk为接收到的所 有操作分配连续的序列号,这些操作可能来自不同的客户机,序列号保证了操作顺序执行。它以序列号的顺序把操作应用到它自己的本地状态中(alex注:也就是在本地执行这些操作,这句话按字面翻译有点费解,也许应该翻译为 “它顺序执行这些操作,并更新自己的状态”)。

5.      主Chunk把写请求传递到所有的二级副本。每个二级副本依照主Chunk分配的序列号以相同的顺序执行这些操作。

6.      所有的二级副本回复主Chunk,它们已经完成了操作。

7.      主Chunk服务器(alex注:即主Chunk所在的 Chunk服务器)回复客户机。任何副本产生的任何错误都会返回给客户机。在出现错误的情况下,写入操作可能在主Chunk和一 些二级副本执行成功。(如果操作在主Chunk上失败了,操作就不会被分配序列号,也不会被传递。)客户端的请求被确认为失败,被修改的region处于 不一致的状态。我们的客户机代码通过重复执行失败的操作来处理这样的错误。在从头开始重复执行之前,客户机会先从步骤(3)到步骤(7)做几次尝试。

Ø  快照

我们用标准的copy-on-write技术实现快照。当Master节点收到一个快照请求,它首先取消作快照的文件的所有Chunk的租约。这个措施保证了后续对这些Chunk的写操作都必须与Master交互交互以找到租约持有者。这就给 Master节点一个率先创建Chunk的新拷贝的机会。

租约取消或者过期之后,Master节点把这个操作以日志的方式记录到硬盘上。然后,Master节点通过复制源文件或者目录的元数据的方式,把这条日志记录的变化反映到保存在内存的状态中。新创建的快照文件和源文件指向完全相同的Chunk地址。

在快照操作之后,当客户机第一次想写入数据到Chunk C,它首先会发送一个请求到Master节点查询当前的租约持有者。Master节点注意到Chunke C的引用计数超过了1(alex注:不太明白为什么会大于1.难道是Snapshot没有释放引用计数?)。 Master节点不会马上回复客户机的请求,而是选择一个新的Chunk句柄C`。之后,Master节点要求每个拥有Chunk C当前副本的Chunk服务器创建一个叫做C`的新Chunk。通过在源Chunk所在Chunk服务器上创建新的Chunk,我们确保数据在本地而不是通过网络复制(我们的硬盘比我们的100Mb以太网大约快3倍)。从这点来讲,请求的处理方式和任何其它Chunk没什么不同:Master节点确保新 Chunk C`的一个副本拥有租约,之后回复客户机,客户机得到回复后就可以正常的写这个Chunk,而不必理会它是从一个已存在的Chunk克隆出来的。è如果某个文件的元数据存在snapshot,则在修改其chunk时,先要将chunk在本地chunk server上复制一份(所有replica也需要复制一份),然后修改复制的chunk,而不是直接修改源chunk

Ø  垃圾回收

当一个文件被应用程序删除时,Master节点立刻把删除操作以日志的方式记录下来。但是,Master节点并不马上回收资源,而是把文件名改为一个包含删除时间戳的、隐藏的名字。当Master节点对文件系统命名空间做常规扫描的时候,它会删除所有三天前的隐藏文件 (这个时间间隔是可以设置的)。直到文件被真正删除,它们仍旧可以用新的特殊的名字读取,也可以通过把隐藏文件改名为正常显示的文件名的方式“反删除”。当隐藏文件被从名称空间中删除,Master服务器内存中保存的这个文件的相关元数据才会被删除。

在对Chunk名字空间做类似的常规扫描时,Master节点找到孤儿Chunk(不被任何文件包含的Chunk)并删除它们的元数据。 Chunk服务器在和Master节点交互的心跳信息中,报告它拥有的Chunk子集的信息,Master节点回复Chunk服务器哪些Chunk在 Master节点保存的元数据中已经不存在了。Chunk服务器可以任意删除这些Chunk的副本。

Ø  容错与诊断

为了保证Master服务器的可靠性,Master服务器的状态也要复制。Master服务器所有的操作日志和checkpoint文件都被复制到多台机器上。对Master服务器状态的修改操作能够提交成功的前提是,操作日志写入到Master服务器的备节点和本机的磁盘。

此外,GFS中还有些“影子”Master服务器,这些“影子”服务器在“主”Master服务器宕机的时候提供文件系统的只读访问。它们是影子, 而不是镜像,所以它们的数据可能比“主”Master服务器更新要慢。“影子”Master服务器为了保持自身状态是最新的,它会读取一份当前正在进行的操作的日志副本,并且依照和主Master服务器完全相同的顺序 来更改内部的数据结构。和主Master服务器一样,“影子”Master服务器在启动的时候也会从Chunk服务器轮询数据(之后定期拉数据),数据中包括了Chunk副本的位置信息;“影子”Master服务器也会定期和Chunk服务器“握手”来确定它们的状态。在主Master服务器因创建和删除副本导致副本位置信息更新时,“影子”Master服务器才和主Master服务器通信来更新自身状态。

 

原创粉丝点击