GFS分布式文件系统

2017-04-06 by subond

分布式文件系统主要有两个功能:一个是存储文档,图像,视频之类的Blob类数据;一个是作为分布式表格系统的持久化层。分布式文件系统中最著名的就是Google File System(GFS),因此,本章通过介绍GFS的内部实现机制来学习分布式文件系统的知识与设计。

1 整体架构

GFS整体架构

一个GFS系统中的节点有三种角色:GFS主控服务器(GFS Master),GFS数据块服务器(GFS ChunkServer)和GFS客户端

GFS存储系统中的文件被分割成固定大小的数据块(chunk),在chunk创建时,Master服务器给每个chunk分配一个全局唯一的chunk句柄。数据块服务器(ChunkServer,CS)把chunk以linux文件的形式存储到磁盘中,并根据指定的chunk句柄和字节范围来读写数据。为了保证可靠性,chunk在不同的服务器中复制多个副本,默认是三份。

主控服务器维护系统的元数据,包括文件,chunk命名空间,文件到chunk之间的映射关系,chunk位置信息。同时,也负责整个系统的全局控制,如chunk租约管理,垃圾回收无用的chunk,chunk复制等。主控服务器 周期地 与CS服务器通过 心跳的方式 交换信息。

客户端是GFS提供给应用程序的访问接口,它是一组专用接口,不遵循POSIX规范,以库文件的形式提供。客户端访问GFS时,首先访问主控服务器节点,获取与之交互的CS信息,然后直接访问这些CS,完成数据存取工作。值得注意的是,GFS客户端不缓存文件数据,只缓存主控服务器中获取的元数据。

2 关键问题

2.1租约机制

GFS系统中通过租约机制将chunk写操作授权给ChunkServer,从而减轻Master的负载。拥有租约授权的ChunkServer称为主ChunkServer,其他副本所在的ChunkServer称为备ChunkServer。主ChunkServer可以不断向Master请求延长租约的有效期直到整个chunk写满。

2.2一致性模型

GFS系统主要是为了追加(append)而不是改写(overwrite)而设计的。如果不发生异常,追加成功的记录在GFS的各个副本中是确定并且严格一致的;如果出现异常,客户端将追究重试,直至成功(所有副本中至少成功追加一次)。

2.3追加流程

追加流程如下所示:

gfs-append

1)客户端向Master请求chunk每个副本所在的ChunkServer,其中主ChunkServer持有修改租约。如果没有ChunkServer持有租约,说明该chunk最近没有写操作,Master会发起一个任务,按照一定的策略将chunk的租约授权给其中的一台ChunkServer。

2)Master返回给客户端主副本和备副本所在的chunk的位置信息,客户端将缓存这些信息供以后使用。如果不出现故障,客户端以后读写该chunk都不需要再次请求Master。

3)客户端将追加的记录发送到每一个副本中,每一个ChunkServer会在内部的LRU结构中缓存这些数据。GFS中采用数据流和控制流分流的方法,从而能够基于网络拓扑结构更好地调度数据流的传输。

4)当所有副本都确认收到了数据,客户端发起一个写请求控制命令给主副本。由于主副本可能收到多个客户端对同一个chunk的并发追加操作,主副本将确定这些操作的顺序写入本地。

5)主副本把写请求提交给所有的副本。每一个备副本会根据主副本确定的顺序执行写操作。

6)备副本成功完成后应答主副本。

7)主副本应答客户端,如果有副本发生错误,将出现主副本写成功但某些备副本不成功的情况,客户端将重试。

GFS追加有两个特色:流水线及分离数据流和控制流。流水线操作可以减少延时。分离数据流和控制流主要为了优化数据传输,每一台机器都是把数据发送给网络拓扑图上”最近“的尚未收到数据的节点。

2.4容错机制

1)Master容错

Master容错通过操作日志加checkpoint的方式进行,并有一台称为“Shadow Master”的实时热备。Master的修改操作总是先记录操作日志,然后修改内存。当Master发生故障重启时,可以通过磁盘中的操作日志恢复内存中的数据结构。与此同时,为了减少Mater宕机的恢复时间,Master定期将内存中的数据以checkpoint文件的形式转储到磁盘中,从而减少回放的日志量。为了进一步提供Master的可靠性和可用性,所有的元数据修改操作都必须保证发送到实时热备才算成功。

补充知识:元数据

主控服务器存储三种主要类型的元数据:

文件和chunk命名空间,也就是整个文件系统的目录结构以及chunk基本信息;

文件和chunk的映射关系

每个chunk副本的位置信息,默认情况下,每个chunk有三个副本。

所有的元数据都保存在Master服务器的内存中。同时,前两种类型的元数据(文件和chunk命名空间,文件和chunk映射关系)也会以记录的方式记录在操作系统的系统日志中,并存储在持久化介质上,另外,日志会复制到其他远程的主控服务器上进行热备。这样做的目的是,提供简单的可靠性,保证主控服务器崩溃的情况下数据的一致性。

每个chunk的元数据不超过64字节。那么1PB数据的chunk元数据大小不超过1PB x 3 / 64MB x 64 = 3GB。

2)ChunkServer容错

简单来讲,ChunkServer容错包括 副本校验和 两种方式。GFS采用复制多个chunk副本的方式实现ChunkServer容错,每个chunk的多个存储副本分别存储在不同的ChunkServer上。对于每个chunk,必须将所有的chunk副本全部写入成功,才视为成功写入。若出现某个副本丢失或者不可恢复时,Master自动将副本复制到其他ChunkServer,确保副本保持一定的个数。ChunkServer会对存储的数据维持校验和。每个64MB大小的chunk以Blok单位进行划分,Block大小为64KB,每个Block对应一个32位的校验和。若读取一个chunk副本时,ChunkServer通过读取数据和校验和进行比较,如果不匹配,则返回错误,客户端将选择其他ChunkServer上的副本。

3 Master设计

3.1名称空间和锁

在逻辑上,GFS的名称空间是一个全路径和元数据映射关系的查找表(前缀压缩)。在存储名称空间的树型结构上,每个节点都有一个关联的读写锁。例如,一个操作设计/d1/d2/.../dn/leaf,那么操作首先获得目录/d1, /d1/d2, ..., /d1/d2/.../dn的读锁,以及/d1/d2/.../dn/leaf的读写锁。

演示:/home/user被快照到/save/user,如何防止创建文件/home/user/foo

1)快照操作获取/home和/save的读取锁,以及/home/user和/save/user的写入锁

2)文件创建操作获取/home和/home/user的读取锁,以及/home/user/foo的写入锁

两个操作要顺序执行,因为它们试图获取的/home/user的锁是相互冲突的。文件创建操作不需要获取父目录的写入锁,文件名的读取锁足以防止父目录被删除。

优点:支持同一目录的并行操作。

3.2负载均衡

chunk副本位置选择的策略服务于两个目标:最大化数据可用性和可靠性,最大化网络带宽利用率。多个机架间分布存储chunk副本

系统中需要创建chunk副本的三种情况:chunk创建,chunk复制以及负载均衡。

当Master创建一个chunk,它会根据一下策略选择chunk副本的位置:1)用ChunkServer的磁盘利用率较低(比如低于平均水平)存储新的副本;2)限制每个ChunkServer“最近”创建的数量;3)每个chunk的所有副本不能在同一个机架上。关于第二点,如果不限制”最近“创建的数量,当一台空的ChunkServer上线时,由于磁盘利用率低,会造成大量的数据迁移。

最后,Master会定期扫描当前的副本的分布情况,当出现磁盘使用量或负载不均衡时,将执行重新负载均衡操作。

3.3垃圾回收

GFS采用延迟删除机制,即当删除文件后,GFS并不要求立即归还可用的物理存储,而是在元数据中将文件改为一个隐藏的名字,并且包含一个删除时间戳。Master定期检查,如果发现文件删除超过一定的时间(默认三天),那么它会把文件从内存元数据中删除。之后,在ChunkServer和Master的心跳信息中,每一个ChunkServer都将报告自己的chunk集合,Master回复在元数据中已经不存在的chunk信息,进而ChunkServer释放chunk副本空间。

3.4快照

快照(Snapshot)操作是对源文件/目录进行一个”快照“操作,生成该时刻源文件/目录的一个瞬间状态存放在目标文件/目录中。GFS中使用标准的写时复制机制生成快照,即只是增加GFS中chunk的引用计数。对某个文件执行快照的大致如下:

1)通过租约机制回收对文件的每个chunk的写权限,停止对文件的写服务;

2)Master拷贝文件名等元数据生成一个新的文件快照;

3)对执行快照的文件的所有chunk增加引用计数。

4 ChunkServer的设计

ChunkServer管理大小为64MB的chunk,存储的时候需要保证chunk尽可能均匀地分布在不同的磁盘中。

基本知识点

chunk尺寸

GFS系统中chunk的大小是64MB。每个chunk的副本都以普通Linux文件的形式保存在CS服务器中。采用较大的chunk尺寸具有以下优点:1)可以减少客户端与主控服务器的请求次数。只需要一次与主控服务器的交互就可以获取chunk的位置信息,然后缓存到客户端,之后就可以对同一个chunk进行多次读写操作。2)因为客户端能够对一个chunk进行多次操作,客户端与数据块服务器保持较长时间的TCP连接,可以减少网络负载。3)一定程度上减少了主控服务器中需要保存的元数据的数量。

chunk位置信息

主控服务器并不持久化保存数据块服务器中的chunk信息,而是在启动时轮询数据块服务器以获取这些信息,并且周期性地通过心跳信息监控数据块服务器的状态。这样做的目的是 在数据块服务器加入集群,离开集群,更名,失效,以及重启的时候,主控服务器可以保证与数据块服务器中chunk信息的一致性

操作日志

主控服务器在日志增长到一定量时对系统状态做一次checkpoint,将所有的状态数据写入一个checkpoint文件。在灾难恢复的时候,主控服务器通过读取磁盘上的checkpoint文件,以及重演checkpoint之后的有限个日志文件就能够恢复系统。checkpoint文件以压缩B树的数据结构存储。