GFS

一、GFS是什么

谷歌文件系统(GFS)就是一个存放数据的分布式文件系统,个人理解就是一个可以在多台计算机上存储数据的系统,是其他上层系统(BigTable等)的基础。

1、GFS核心思想

GFS追求的是整体系统的稳定性,其处理对象是大数据。其指导思想为:

  1. 组件故障被当做一种常态进行处理
    也就是说,不认为系统内的每一台计算机都是可靠的。虽然组件故障是正常的,但是需要有措施保障整个系统的正常运行。
  2. 对于吉字节数量级的大文件的处理
    说明了GFS的处理对象是大文件,但是仍需要支持小文件,不过不会对小文件进行专门优化。
  3. 绝大部分修改是追加数据
    实际中随机写入几乎不存在,文件的修改就是追加数据。文件一旦写完后,对文件的操作就只有读,而且一般是顺序读。GFS仍然支持小规模的随机写,但是不保证效率。
  4. 应用程序和文件系统API的协同设计提高整个系统的灵活性
    放松了对GFS一致性模型的要求。

2、一致性

文件命名空间的修改是原子性的,仅由master服务器控制,master服务器控制方式包括:

  1. 命名空间锁提供了原子性和正确性保障。
  2. 操作日志定义了操作的顺序。

1)、一致性模型

操作的结果有以下几类:

  1. 一致的
    对于所有客户端,无论从哪个副本读取,读到的数据都一样。
  2. 已定义的
    一致的,并且客户端能够看到写入操作的全部内容。一个数据修改操作未受到其他操作的干扰,那么它就是已定义的。并行操作修改完成之后,文件内容包含了多个来自不同客户端的混杂的数据片段,处于一致的、未定义的状态。
  3. 失败的
    结果处于不一致状态。

2)、一致性保障

GFS通过以下操作保证数据是一致的:

  1. 对chunk所有副本的修改操作顺序一致
  2. chunk版本号
    使用chunk的版本号检测chunk是否因为所在服务器宕机而错过修改,master服务器不会返回失效的副本的位置给客户端,它们会被尽快回收。但是,客户端可能会缓存chunk位置信息,这就导致客户端有可能会读取失效的数据。不过,由于修改一般是追加操作,所以客户端读到的是提前结束的chunk,而不是过期的数据。
  3. 定期握手
    在修改操作执行成功一段时间后,组件也有可能会失效。GFS通过master服务器和所有chunk服务器定期握手来找到失效的chunk服务器,并使用checksum校验数据是否正确,一旦数据损坏,要尽快利用副本进行恢复。

二、读写操作

客户端首先访问master服务器以获得chunk服务器信息,然后访问chunk服务器完成数据读写。client与master之间只有控制流,大大降低了master的负载。client与chunk服务器直接传输数据流,由于每个文件被分成多个chunk,整个系统的IO高度并行。

1、租约与变更

  1. 租约
    master服务器为chunk的一个副本建立一个租约,这个副本就被称为主chunk。设计租约的目的是最小化master服务器的管理负担。租约的初始超时设置为60s,不过,只要chunk被修改了,主chunk就可以申请更长的租期。
  2. 变更
    变更是会改变chunk内容或元数据的操作,如写入、记录追加。变更操作会在chunk所有副本上执行。使用租约来保证变更顺序一致性。主chunk对chunk所有更改操作进行序列化,所有副本都遵循这个序列进行修改操作。

2、数据修改

数据修改分为写入和记录追加。写入操作是把数据写在应用程序指定的偏移位置上,而并行化的记录追加的偏移位置是由GFS选择的。 如果一次写入的数据量很大,client会分成多个写操作。此时可能会出现一致但未定义的结果。
修改流程
修改的过程如下:

  1. client向master询问哪个chunk服务器持有当前租约以及其他副本的位置,如果没有chunk持有租约,就这各副本中选择一个建立租约。
  2. master将主chunk标识及各副本位置返回给client,客户机缓存这些信息。只有主chunk不可用或者主chunk回复信息表明其不再持有租约时,client才重新与master联系。
  3. 客户机把数据推送到所有副本上。客户机可以以任意顺序推送,chunk服务器接收到数据,并把其保存在内部LRU缓存中,一直到数据被使用或者过期交换出去。
  4. 当所有副本都确认接收到数据,client发送写请求到主chunk服务器,主chunk为接收到的所有操作分配连续的序列号,并按照序列号本地执行这些操作。
  5. 主chunk将写请求传递给所有副本,每个副本按照相同的序列号执行操作。
  6. 所有副本回复主chunk已完成操作。
  7. 主chunk服务器回复client操作执行结果。

3、数据流

为了提高网络效率,数据流和控制流分开处理。在数据从client到每一个chunk服务器的过程中,数据沿着一条精心选择的chunk服务器链推送。
为了充分利用每台机器的带宽,数据沿着一个chunk服务器链顺序推送,而不是以其他拓扑形式分散推送。在线性模式下,每台机器的所有出口带宽都用于以最快的速度传输数据,而不是在多个接收者之间分配带宽。为了避免高延迟的连接,每台机器都尽量在网络拓扑中选择一台没有接收数据的、离自己最近的机器作为目标。

三、API

GFS的API包括创建、删除、打开、关闭、读、写、快照、记录追加,对于后4种而言:


  1. 读分为大规模的流式读取和小规模的随机读取,一般都是前者。

  2. 写一般是追加操作,而花费最小的同步开销来保证多路追加操作的原子性是必不可少的,这是因为一般会有很多客户端同时写数据。
  3. 快照
    快照是以低成本来创建一个文件或目录树的拷贝,几乎可以瞬间完成对一个文件或目录树的拷贝,并且几乎不会对正在进行的其他操作造成干扰。
    当master服务器接收到一个快照请求,它首先取消快照文件的所有chunk的租约,用于保证此后所有对该文件的写操作都必须与master交互以找到租约持有者,使得master可以率先创建一个新拷贝。
    租约取消或者过期后,master把这个操作以日志的形式保存在硬盘上。然后master服务器通过复制源文件或者目录的源数据的方式,把这条日志记录的变化反映到保存在内存的状态中,新创建的快照文件与源文件指向相同的chunk地址。
    快照操作之后,当client想写数据到文件中时,它首先会发送一个请求到master服务器查询租约持有者。master注意到该文件的引用计数超过1,不会马上回复client的请求,而是选择一个新的chunk句柄C’。之后,master结点要求每个拥有该文件当前副本的的chunk服务器创建一个叫做C’的chunk。通过在源chunk所在chunk服务器上创建新chunk,保证数据不通过网络传输。
  4. 记录追加
    记录追加是允许多个客户端同时对一个文件追加数据,同时保证追加操作的原子性。
    使用记录追加,client只需要指定要写入的数据,GFS保证至少有一次原子的写入操作成功执行。记录追加遵循修改流程,不过在主chunk有一些额外的控制逻辑。主chunk会检查记录追加操作是否会使当前chunk超过最大尺寸,如果超过了最大尺寸,主chunk首先将当前chunk填充到最大尺寸,之后通知所有副本做相同操作,然后回复client要求其对下一个chunk重新进行记录追加操作。
    如果记录追加操作失败了,client就需要重新进行操作,其结果是同一个chunk的不同副本可能包含不同的数据:重复包含一个记录部分或者全部的数据。GFS并不保证chunk的所有副本在字节级别完全一致,它只保证作为一个原子的数据被至少被写入一次。

四、体系结构

GFS体系结构
GFS包括一台master服务器、多台chunk服务器以及多个客户端。
在GFS中,文件被分成固定大小的chunk,在chunk创建的时候,会分配给它一个不变的、唯一的标识。每个块都会以副本的形式复制到多个服务器上,默认数量是3个。

1、master服务器

master服务器管理所有的文件系统元数据,包括命名空间、访问控制信息、文件和chunk的映射信息、chunk的位置信息。此外,master服务器还负责很多活动,如chunk租用管理、孤儿chunk的回收、chunk在chunk服务器中的迁移。最后,master服务器使用心跳信息获得chunk服务器状态信息。

1)、元数据

master服务器存储3种类型的元数据:文件和chunk的命名空间、文件和chunk的对应关系、每个chunk副本的位置。所有的元数据都保存在master内存中,前2种元数据也会以日志的形式保存在系统日志文件中,并复制到其他master服务器上。master服务器不会持久的保存chunk位置信息,master服务器启动时或者新的chunk服务器加入时,master服务器向各个chunk服务器轮询存储的chunk信息。

①、chunk位置信息

master服务器并不持久化保存chunk存储在哪个chunk服务器上,master服务器会在启动的时候轮询chunk服务器获得信息。因为master服务器控制所有chunk的分配,所以其拥有最新的信息。

②、操作日志

操作日志包含了关键的元数据变更记录,是元数据的唯一持久化存储记录。日志会被复制到多台远程服务器上,并且只有在日志被写入本地和远程机器硬盘后,才会响应客户端的操作请求。同时,master服务器采用检查点技术,以保证在灾难发生时快速恢复。

2)、master结点的操作

master结点执行所有的名称空间操作,还管理着整个系统里所有chunk的副本:它决定chunk的存储位置,创建新chunk和它的副本,协调各种各样的系统活动以保证chunk被完全复制,在所有的chunk服务器之间进行负载均衡,回收不再使用的存储空间。

①、命名空间管理和锁

master服务器的很多操作会花费很长时间,比如快照必须取消chunk服务器上所有快照涉及的chunk的租约。为了执行这些操作时,不影响master服务器上其他操作,允许多个操作同时进行,使用命名空间上的锁来保证正确的执行顺序。
GFS没有针对每个目录实现能够列出目录下所有文件的数据结构,GFS也不支持文件或目录的链接。在逻辑上,GFS的命名空间就是一个全路径与元数据映射关系的查找表。在存储命名空间的结构上,每个文件名或目录名都有一个与之关联的读写锁。
每个master结点的操作开始之前都要获得一系列的锁,如果一个操作涉及/d1/d2/···/dn/leaf,则需要获得/d1/d2/···/dn的读锁以及/d1/d2/···/dn/leaf的读写锁。leaf可能是一个文件,也可能是一个目录。通过采用这种锁的机制,可以支持对同一目录的并行操作。锁在不用的时候会被立即删除,锁的获取需要有一个全局一致的顺序避免死锁。

②、副本的位置

chunk副本位置选择策略有2大目标:最大化数据可靠性和可用性、最大化网络带宽利用率。因为GFS集群一般是数百台chunk服务器安装在许多机架上,所以仅在多台机器上存储副本是不够的,必须在多个机架间分布式存储副本。

③、创建、重新复制、重新负载均衡

当master结点创建一个新的chunk时,在选择存储位置上会考虑一下因素:

  1. 在低于平均硬盘使用率的chunk服务器上存储新的副本
  2. 限制在每个chunk服务器上最近的chunk创建操作次数
  3. 把chunk的副本分布在多个机架之间

当chunk的有效副本数量小于用户指定的复制因数的时候,比如chunk服务器不可用,master结点会重新复制它。多个需要复制的chunk会根据策略排序,master服务器选择优先级最高的chunk,命令某个chunk服务器直接从某个可用副本中克隆一个新的副本,其存储位置考虑因素同创建时一样。
master结点会周期性的对副本进行重新负载均衡。

④、垃圾回收

GFS在文件删除后不会立即回收空间,GFS空间回收采用惰性策略,只在文件和chunk级的常规垃圾收集时进行。
当一个文件被删除时,master结点立即把操作以日志的形式记录下来。但是,master结点并不马上回收结点,而是把文件名改成一个包含时间戳的、隐藏的名字。当master服务器对命名空间做常规扫描时,它会删除所有3天前的隐藏文件。在文件被真正删除前,可以通过新的特殊名字读取,或者把文件名改成正常文件名来取消删除。当隐藏文件从命名空间中删除,master服务器内保存的相关元数据才会删除,也就切断了文件和其对应的所有chunk的连接。
在对命名空间做常规扫描时,master结点找到孤儿chunk并删除相应元数据。在master与chunk的心跳交互时,chunk服务器报告它所拥有的chunk子集信息,master服务器回复chunk服务器哪些chunk的元数据已经不在,chunk服务器可以任意删除这些chunk。

⑤、过期失效副本的检测

当chunk服务器失效时,chunk的副本可能因为错过了修改而失效。master服务器保存了每个chunk的版本号,用来区分当前副本和过期副本。
只要master结点和chunk签订一个新的租约,它就增加chunk的版本号。master服务器和副本都将新的版本号记录在持久化保存的状态信息中。如果chunk服务器失效,那么副本的版本号就不会增加。当该chunk服务器重新启动时会向master服务器报告它所拥有的chunk和相应的版本号,master服务器就会检测出过期的chunk。
master服务器在垃圾回收过程中移除所有的失效副本。在此之前,master服务器在回复client的chunk信息请求时,会简单的认为那些过期的块不存在。此外,master在通知client哪个chunk服务器持有租约或者指示chunk服务器从哪个chunk服务器克隆时,消息中都附带了版本号。

2、chunk服务器

chunk服务器用来存储文件,其存储的单位是块。每块的大小为64MB,这个大小保证了元数据的数量较少,可以有效减轻master的负载。

五、容错

组件的数量与质量让错误的发生不可避免,无论是机器还是硬盘都不可靠,需要采取一些措施去应对这些问题。

1、高可用性

在数百台服务器中,必定有一些是不可用的。使用两条策略保证系统的高可用性:快速恢复和复制。

1)、快速恢复

不管是master服务器还是chunk服务器都不区分正常关闭和异常关闭,它们被设计成可以在数秒内恢复状态并重新启动。client可能会感觉系统有些颠簸,正在发出的请求会超时,需要重新连接重启的服务器。

2)、chunk复制

每个chunk都被复制到不同机架的服务器上,缺省的复制因数是3。当chunk服务器离线或者chunk损坏时,master通过复制已有副本保证chunk被完整复制。

3)、master服务器的复制

为保证master服务器的可靠性,master服务器的状态也需要复制。master服务器的所有操作日志和checkpoint文件都被复制到多台机器上。只有相关操作日志被写入master服务器和后备结点的的磁盘,对master服务器状态的修改操作才能成功提交。
master服务器有一个进程负责所有的修改操作,包括垃圾回收等。当它失效时,几乎可以立即重新启动。当他所在的机器或磁盘失效时,GFS系统外的监控进程会在其他有完整操作日志的机器上启动一个新的master进程。
此外,GFS中还有一些影子master服务器,它们的数据可能比主master服务器更新要慢,在主master服务器宕机的时候提供文件系统只读访问。这对于不经常改变文件或允许数据有少量过期的应用程序来说,可以提高读取效率。因为数据是存储在chunk服务器上,过期的不会是文件内容,而是文件的元数据。
为了保证自身状态是最新的,影子master服务器会读取当前正在进行的操作的日志副本,并依照和主master服务器完全相同的顺序改变内部数据结构。影子master服务器启动的时候,会轮询chunk服务器获取chunk信息。也会定期和chunk服务器握手来确定它们的状态,只有主master服务器因为创建和删除副本导致其位置信息更新时,影子master服务器才和主master服务器通信来更新自身状态。

2、数据完整性

chunk服务器通过checksum来检查保存的数据是否损坏,跨服务器比较副本是不实际的。GFS允许有歧义的副本存在,即不保证副本完全相同。所以每个chunk服务器需要独立维护checksum来校验副本的完整性。
每个chunk被分成64KB大小的块,每个块对应一个32位的checksum。和其他元数据一样,checksum和用户数据是分开的,保存在内存和硬盘上,同时也记录操作日志。
对于读操作来说,在把数据返回给client或其他chunk服务器之前,chunk服务器会校验涉及到的chunk的checksum,保证不会把错误的数据传递到其他机器上。如果chunk不正确,chunk服务器返回给请求者一个错误信息,并通知master服务器这个错误。请求者会从其他副本处读数据,master服务器也会clone一个新的副本,新的副本就绪后,master服务器通知错误副本的chunk服务器删除错误的chunk。
checksum的计算针对记录追加操作做了高度优化,只增量更新最后一个不完整的块的checksum,并且用所有追加来的新checksum块来计算新的checksum。保证即使最后一个不完整的checksum块已经损坏且不能马上检测出来,由于新的checksum与已有数据不吻合,在下次对这个块进行读操作时,会检查出数据已经损坏。
对于写操作而言,如果其覆盖一个chunk,就必须读取和校验被覆盖的第一个和最后一个块,然后在执行写操作,否则新的checksum可能会隐藏未被覆盖的区域的数据错误。操作完成后,还需要重新计算和写入新的checksum。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值