本文是对论文《The Google File System》的记录. 这篇论文也是谷歌关于大数据的三大论文之一, 主要讲述了一种新的可扩展的分布式文件系统的设计与实现. 大数据处理系统Hadoop中的Hadoop Distributed File System是Google File System的开源实现.

阅读提示

这篇论文从语言方面来看, 单词和语句都比较容易理解, 阅读难度大概等于英语六级水平. 但其中涉及了很多新的概念, 理解有关的概念并不容易, 如果对Hadoop有一点了解阅读起来会轻松很多.

概述

Google File System(GFS)是一个可扩展的分布式文件系统, 具有一定的错误容忍能力, 从而可以构建在廉价的设备之上, 并且为大量的客户提供强大的服务能力. 在GFS的开发过程中, 研究人员发现实际的需求与以往的分布式系统中的假定并不完全相同, 因此GFS使用了一些新的假设. GFS的产生源于Google对大数据的处理需求, 因此论文中也涉及了大量关于实际使用的问题.

基本前提

基本假设

GFS的设计过程中引入了如下的一些假设:

  1. 故障是常态而不是异常
  2. 文件大小远大于传统文件
  3. 文件通常进行追加操作而不是随机写入

故障包括软件层面的应用程序BUG和系统BUG, 硬件层面上的磁盘故障和内存故障以及操作层面上的操作失误, 对于这些问题, 系统需要有对故障的监控,处理和恢复能力. 由于单个文件的体积显著增大, 而小文件的使用需求相对减少, 因此在此假设上可以设计新的I/O方式, 从而提高系统的效率. 由于实际的使用场景, 因此很多文件通常只进行追加操作, 而不会进行随机写入, 因此可以从充分利用这一点进行优化.

设计假设

在系统的设计过程中, 有如下的一些假设

假设 解释
廉价设备 系统运行在大量廉价设备组成的集群上
超大文件 单个文件体积大, 支持小文件但不进行优化
连续读取 大量连续的读取, 少量随机的读取
追加写入 文件追加写入, 一旦写入不可修改
一致性处理 系统能有效的运行在生产者-消费者模型下
提高带宽 高带宽比低延时更重要

系统架构

GFS 架构

一个GFS集群具有一个master节点和多个chunkserver节点, 可以同时为多个客户提供服务. 文件被分割为适当大小的chunk, 存放在chunkserver之上. 对于每个chunk, 默认都会冗余的存储三份. master保存所有的元数据, 包括文件名, 访问权限, 文件与chunk的映射关系, 每个chunk在具体节点中的位置等. master与各个chunkserver通过心跳包的方式传递之类和返回状态.

客户端(应用程序)向master发送文件请求信息, master返回chunk的相关信息, 之后客户端直接与相应的chunkserver通信.

Chunk Size

Chunk Size的设置是一个重要的参数, 一个大的size有如下三个方面的影响

  1. 减少文件分裂的chunk数, 从而减少客户端与master的通信量
  2. 使得大量操作在同一个chunk上进行, 可以充分利用TCP保存连接的特性
  3. 减少master上元数据的数据量,从而使元数据可以保存在内存之中

但是大的size也存在问题, 如果某个文件是热点文件, 则可能导致某个chunkserver读写压力过大. 但实际运行而言, 这并不是一个严重的的问题.

Metadata

master存储的元数据主要有三个方面, 文件和chunk的名字, 两者的映射关系以及每个chunk的具体位置. 所有的元数据都保存在内存之中, 但前两种数据来通过日志的方法保存到磁盘上, 从而对数据进行修改时不会产生一致性的问题.

master不持久保存chunk的位置信息, 而是在master节点启动时或有新的chunkserver加入时, 向各个chunkserver查询位置信息. 这种方法使得master的信息不必随着chunkserver文件的修改, 删除或chunkserver的加入, 重启而同步的改变. 由于具体的chunkserver决定一个文件是否存在, 因此不必保证master的信息与chunkserver的信息完全同步.

OperationLog

操作日志保存了master节点上所有的修改. 如果master节点出现故障, 可以通过重新执行日志中的操作来恢复原来的状态. 为了减少恢复时间, 每当日志大小达到一定体积时, master节点就创建一个checkpoint, 之后当master需要恢复时, 可以先加载最新的checkpoint中, 然后只需要重新执行该checkpoint之后少量的操作.

checkpoint采用紧缩的B-tree结构, 可以直接加载到内存之中. checkpoint的创建位于独立的线程, 创建过程不影响系统的继续使用.

主节点操作

主节点执行所有的名称操作(创建,重命名,删除等), 此外主节点还负责备份的管理, chunk位置的分配, 负载均衡, 垃圾回收等.

名称操作

由于名称操作可能消耗很多时间, 例如snapshot操作需要访问各个涉及到的chunkserver至少一次. 因此, 在GFS中, 允许同时进行多个操作, 通过读写锁机制来实现一定的顺序.

副本位置选择

选择副本位置有两个目标

  1. 最大化数据的可靠性和可用性
  2. 最大化网络资源利用率

为了实现上述目标, 仅仅将数据分布到同一个机架的不同的机器上是不够的, 这样只能保证磁盘或者机器故障时的数据可用性. 只有将数据分布到不同机架上的机器上时, 才可以保证网络设备故障等原因下导致整个机架上的设备离线时还可以提供服务.

将数据分布到不同机架后, 客户端可以从不同的位置读取数据, 能够更充分的利用带宽资源. 但此时如果需要写入数据, 也会导致需要向多个位置发送写入数据, 这也是一个权衡后的结果.

负载均衡

一个chunk的创建有三个原因, 即创建新文件, 创建副本, 负载均衡. 当创建一个chunk时, 关于位置的选择有如下的三个需求

  1. 平衡各个机器的负载
  2. 避免在一个机器上频繁的创建chunk
  3. 将副本分布到不同机架上的设备

对于第二点, 由于GFS在设计时的目标是数据一次写入, 多次读取, 因此处于可靠性的的考虑, 每一台设备都并支持长时间持续的写入数据.

无论是创建新的文件, 还是创建副本或负载均衡, GFS都按照以上的需求调整chunk的位置.

垃圾回收

在一个文件被删除以后, GFS并不会立刻处理相关的物理存储, 而是做了一个标记, 在之后master节点周期性的扫描过程中, 发现这些节点以后, 就删除对应的的元数据并通知各个chunkserver可以删除此文件. 通过这种方式, 可以使得系统更加简单可靠.

虽然分布式的垃圾回收是一个复杂的问题, 但在GFS中却十分简单. 因为master节点维护了文件和chunk的映射关系, 同时chunkserver也能定位每一个chunk的位置, 因此任何master节点中没有记录的chunk就是垃圾.

这种策略的一个主要问题是删除过程存在一定的延时, 当系统资源比较紧张时无法充分利用释放的资源.

最后更新: 2024年04月24日 15:50

版权声明:本文为原创文章,转载请注明出处

原始链接: https://lizec.top/2018/08/12/%E8%AE%BA%E6%96%87GoogleFileSystem/