Google 早期三驾马车之 GFS 论文学习与研读

前言

Google,作为全球最大的搜索引擎公司,其伟大之处不仅在于建立了一个强大的搜索引擎,还在于它创造了3项革命性的技术,即:GFS、MapReduce 和 BigTable。作为 Google 早期三驾马车,这三项革命性的技术不仅在大数据领域广为人知,更直接或间接性的推动了大数据、云计算、乃至如今火爆的人工智能领域的发展。

2003年10月19—22日,Google 在美国纽约召开的第19届 ACM 操作系统原理研讨会(Symposium on Operating Systems Principles,SOSP)上,发表了论文《The Google File System》(Google 文件系统),系统地介绍了 Google 面向大规模数据密集型应用的、可伸缩的分布式文件系统——GFS。GFS 是一个可扩展的大型数据密集型应用的分布式文件系统,该文件系统可在廉价的硬件上运行,并具有可靠的容错能力,该文件系统可为用户提供极高的计算性能,而同时具备最小的硬件投资和运营成本。

关于 MapReduce 相关介绍与论文研读:查看 MapReduce

关于 BigTable 相关介绍与论文研读:查看 BigTable

随着这3篇重量级论文的发表,基于这3项技术的衍生技术与开源产品如雨后春笋般涌现(Hadoop 就是其中的一个)。至此,Google 以一种独特的方式,推动了大数据处理、云计算等技术的发展。

注:在后 Hadoop 时代,Google 推出新三驾马车 —— Caffeine、Pregel、Dremel

本文学习与研读最初的 GFS 论文,中英双文版见:中英双文版

总览

GFS 论文总览如图所示,主要包含九个部分:简介、设计概述、系统交互、Master 节点的操作、容错和诊断、度量、经验、相关工作、结束语。

一、简介

    1. 定义:Google GFS 文件系统,面向大规模数据密集型应用的、可伸缩的分布式文件系统。
    2. 硬件设备:基于廉价的 PC 端。
    3. 设计思路
            a. 组件失效是常态事件,而非意外事件。
                GFS 在设计之初,就将组件的失效(如宕机、网络瘫痪等)规为常见的问题,所以要求将持续的监控、错误侦测、灾难冗余、自动恢复机制必须集成在 GFS 本身中。
            b. 相对于通常的衡量标准,需要操作的文件巨大。
                经常需要处理快速增长、数亿个对象构成、数以 TB 的数据,为了避免管理数亿个 KB 大小的文件,重新考虑 I/O 操作和 Block 的尺寸。
            c. 绝大部分文件的修改是采用在文件尾部追加数据,而非覆盖原有数据。
                根据实际文件处理情况(如对文件的随机写入操作在实际中几乎不存在等),将追加操作作为性能优化和原子性保证的主要考量因素。
            d. 应用程序和文件系统 API 的协同设计提高了整个系统的灵活性。
                引入原子性的记录追加操作,不需要额外同步操作保证数据一致性。

二、设计概述

    1.设计预期
            a.系统工作负载
            系统工作负载主要包括大规模的流式读取、小规模的随机读取 与 其他情况。
            大规模的流式读取指的是一次性读取数百 KB 数据,更常见的是一次读取 1MB 或更多数据(常见场景);
            小规模的随机读取指的是在文件某个随机位置读取几个 KB 的数据,为了提高读取性能,通常做法是:把小规模的读取操作合并与排序,按顺序读取,这样就避免前后来回移动读取位置;
            其他情况的写操作(大规模、顺序的、数据追加的方式),一般写入数据量与大规模读类似。
            b.文件用途:“生产者-消费者”队列;多路文件合并操作。
            c.要求:高性能的稳定网络带宽 重要性远远大于 低延迟。

    2.接口
            a.GFS 系统中,文件以分层目录的形式组织,用路径来标识。
            b.常用操作:
               创建新文件、删除文件、打开文件、关闭文件、读 / 写 文件 等;
               快照:低成本创建一个文件或目录树的拷贝;
               记录追加:记录追加允许多个客户端同时追加操作一个文件,并保证每个客户端的操作都是原子性;此外允许多个客户端在不需要额外同步锁的情况下,同时对一个文件追加记录。

    3.架构
           a.结构图


            b.GFS 集群构成
               GFS 集群主要由三个部分构成:一个单独的 GFS Master 节点、多台 GFS Chunk(块) 服务器、多个 GFS 客户端。
               一个单独的 GFS Master 节点。即 Hadoop 底层存储 HDFS 的 nameNode 节点的前身。
               一个单独的 Master 节点主要管理所有文件系统元数据(名称空间、访问控制信息、文件和 Chunk 的映射信息、当前的 Chunk 位置信息)、管理系统范围内的活动(Chunk 租用管理、孤儿(orphaned) Chunk 回收、Chunk 在 Chunk 服务器上的迁移)、发送心跳信息保持与每个 Chunk 服务器通讯(发送指令,接受服务器状态信息)。

               多台 GFS Chunk(块) 服务器。即 Hadoop 底层存储 HDFS 的 dataNode 节点的前身。
               GFS Chunk(块) 服务器即 Linux 机器,允许用户级别的服务进程,包含由 Master 服务器分配一个不变且唯一的 Chunk 标识。由于存储在 GFS 中的文件被分割为固定大小的 Chunk,以 Linux 文件的形式保存在硬盘中,根据 GFS 客户端指定的 Chunk 标识与字节范围读写数据。在可靠性方面,由于每个块都会复制到多个块服务器上(用户可设定不同的复制级别),有了冗余备份,系统的可靠性与容灾能力就有了保障。
            
              多个 GFS 客户端
              当多个 GFS 客户端发送请求时,请求顺序如下:对 Master 发送文件名称与块索引 => 获取指定的 Chunk 标识与所在位置 => 客户端以文件名与 Chunk 索引作为 key 缓存这些信息 => 对最近的 Chunk 服务器发送 Chunk 标识与字节范围 => 获取块数据流。
            c.特点:无需缓存数据(Linux 文件系统自动缓存经常访问的数据到内存)。

    4. 单一 Master 节点
        单一  Master 节点的策略简化了设计,减少对 Master 读写,避免其成为系统瓶颈,Master 节点可以通过全局的信息精确定位 Chunk 位置及进行复制决策,另外客户端在一次请求 Master 节点时会查询多个 Chunk 信息,避免多次通讯。

    5. Chunk 尺寸
        a.关键的设计参数之一:64MB(原文中对于此 64MB 的设定并无仔细说明,一般认为是一个经验值)。
        b.特点:惰性空间分配策略(Chunk 的副本在需要的时候才扩大)。
        c.优点:
            减少了客户端和 Master 节点通讯,降低工作负载并且轻松缓存数据集所有 Chunk 的位置信息;
            最小化寻址开销;
            客户端可以对一个块多次操作,与 Chunk 服务器保持长时间 TCP 连接减少网络负载;
            减少 Master 节点需要保存的元数据的数量,允许将全部元数据放入内存。
        d.缺点:
            当多个客户端多次访问小文件时,存放小文件的 Chunk 服务器被高并发请求导致系统局部过载。
            解决方法:使用更大的参数保存可执行文件、错开批处理队列系统程序的启动时间、允许客户端从其他客户端读取数据等。

    6. 元数据
        a.内存中的数据结构
            由于 master 服务器操作速度非常快,在后台周期性扫描保存的全部状态信息(包括 Chunk 垃圾收集、Chunk 服务器失效时重新赋值数据、通过 Chunk 的迁移实现跨 Chunk 服务器的负载均衡、磁盘使用状况统计等),Master 服务器只需要不到 64个字节的元数据管理 64MB 的 Chunk,保存的文件名用前缀压缩算法处理。
        b.Chunk 位置信息
            Master 启动时轮询 Chunk 服务器获取 Chunk 的副本信息,不持久化保存;Master 服务器控制所有的 Chunk 服务器分配位置,周期性的心跳监控 Chunk 服务器的状态,只有 Chunk 服务器才能最终确定一个 Chunk 是否在其中(不能在 Master 服务器上维护一个这些信息的全局视图,因为特殊情况下硬盘损坏了或者无法访问导致 Chunk 自动消失,亦或者操作人员可能会重命名一个 Chunk 服务器)。
        c.操作日志
            操作日志主要包含关键的元数据变更历史纪录,是元数据唯一的持久化存储记录,可以作为判断同步操作顺序的逻辑时间基线,只有在元数据的变化被持久化后,日志才对客户端可见。在灾难恢复方面,重演操作日志将文件系统恢复到最近的状态,为缩短 Master 启动时间,日志必须小,当其增长到一定量时,对数据库状态做一次快照;Master 服务器只要恢复最新的 Checkpoint 文件和后续的日志文件即可。

    7. 一致性模型
        a.GFS 一致性保障机制
            由于文件命名空间的修改是原子性的,它们仅由 Master 节点的控制:命名空间锁提供了原子性和正确性的保障;Master 节点的操作日志定义了这些操作在全局的顺序。写入操作把数据写入到应用程序指定的文件偏移位置上,记录追加操作至少可以把数据原子性的追加到文件中一次,偏移位置由 GFS 选择;
            GFS 确保被修改的文件是最新操作文件的措施有两点,一是对 Chunk 所有副本修改操作顺序一致,二是使用 Chunk 的版本号检测副本是否因为 Chunk 服务器宕机而错过了修改操作而导致其失效;
            一旦发现问题,数据要尽快利用有效的副本恢复。
        b.程序的实现
            目标:尽量采用追加而不是覆盖、Checkpoint、自验证的写入、自标识的记录;
            原因:追加写入比随机位置写入更加有效率,对应用程序的处理更具有弹性。

三、系统交互

    1. 重要原则:最小化所有操作和 Master 节点的交互。

    2. 租约(Iease)和变更顺序
        a.变更:改变 Chunk 内容或者元数据的操作(写、追加),在 Chunk 的所有副本执行。
        b.租约机制
            保持多个副本间变更顺序的一致性。
            过程:Master 节点与一个 Chunk 副本(主 Chunk)建立租约;主 Chunk 对 Chunk 所有更改操作序列化,所有副本遵循此序列进行修改操作;修改操作顺序首先由 Master 节点选择的租约的顺序决定,然后由租约中主 Chunk 分配的序列号决定。
            目的:最小化 Master 节点的管理负担。
        c.写入操作的控制流程

         详细流程说明:
          I. 客户机询问 Master 节点当前租约在哪台服务器上,及其他副本的位置(若无 Chunk 持有租约,Master 选择其中一个副本建立租约);
          II. Master 将主 Chunk 标识符及其他副本位置返回客户机;
          III. 客户机把数据推送到所有副本上(可以以任意顺序推送数据),Chunk 服务器收到数据保存内部的 LRU 缓存,知道数据被使用或过期;
          IV. 所有副本都确认收到了数据,客户机发送写请求到主 Chunk 服务器,请求标识了早前推送到所有副本的数据;
          V. 主 Chunk 把写请求传递到所有二级副本,每个二级副本按照主 Chunk 分配的序列号以相同顺序执行操作;
          VI. 所有二级副本回复主 Chunk 完成操作;
          VII. 主 Chunk 回复客户机(任何错误都会返回客户机,客户机通过重复执行失败的操作处理错误);
          VIII. 从头开始重复执行之前,客户机从步骤 3 到 7 做几次尝试。

        d.特殊情况
            I. 若程序一次写入大量数据,或数据跨越多个 Chunk,GFS 客户端将数据分成多个写操作;
            II. 分解后的写操作在所有副本上以相同顺序执行完成,Chunk 的所有副本都是一致的。

    3. 数据流
        a.措施:提高网络效率,采取将数据流与控制流分开。
        b.过程:控制流从客户机到主 Chunk、然后再到所有二级副本的同时,数据以管道的方式,顺序沿着一个精心选择的 Chunk 服务器链推送(先行推送)
            客户机把数据从 Chunk 服务器 S1 推送到 S4:
            I. 客户机把数据推送到最近的 Chunk 服务器 S1;
            II. S1 把数据推送到 S2;(S2 与 S4 中最接近 S1 的机器是 S2);
            III. S2 把数据传递给 S3 和 S4 之间更近的机器,以此类推;
            通过 IP 地址计算节点的“距离”。
        c.目标:充分利用每台机器的带宽,避免网络瓶颈和高延时的链接,最小化推送所有数据的延时(利用基于 TCP 连接的、管道式数据推送方式)。
        d.推送方式
            I. 管道方式:全双工的交换网络。
            II. 传输延迟
                传送 B 字节的数据到 R 个副本的理想时间:B/T+BL (T:网络吞吐量,L两台机器数据传输延迟);
                通常,网络连接速度 100Mbps(T),L 远小于 1ms。1MB 的数据理想情况下 80ms 左右能分发出去。

    4. 原子的记录追加
        a.特点:
            I. GFS 保证至少一次原子的写入操作成功执行(即写入一个顺序的 byte 流);
            II. 写入的数据追加到 GFS 指定的偏移位置,GFS 返回偏移量至客户机。
        b.流程:
            I. 客户端把数据推送给文件最后一个 Chunk 的所有副本,发送请求给主 Chunk;
            II. 主 Chunk 检查此次记录追加是否会使 Chunk 超过最大尺寸(64MB);
            III. 若超过,主 Chunk 先将当前 Chunk 填充到最大尺寸,通知所有二级副本同样操作,然后恢复客户机要求其对下一个 Chunk 重新记录追加操作;
            IV. 主 Chunk 把数据追加到自己副本内,然后通知二级副本把数据写在与主 Chunk 一样的位置,然后回复客户机操作成功。
        c.意外情况:
            I. 记录追加在任何一个副本上失败,客户端就要重新操作;
            II. 重新记录追加的结果:同一个 Chunk 不同副本可能包含不同的数据(重复包含一个记录全部或部分数据)。

    5. 快照
        a.作用:几乎瞬间完成对一个文件或目录树的一个拷贝,并且几乎无干扰进行中的其他操作。
        b.过程:
            I. Master 节点收到快照请求,取消作快照的文件的所有 Chunk 的租约,保证后续对这些 Chunk 的写操作必须与 Master 交互以找到租约持有者;
            II. 租约取消或过期后,Master 节点在内存中存储操作日志;
            III. Master 节点通过复制源文件或目录的元数据,把这条日志记录的变化保存在内存的状态中;
        c.特点:新创建的快照文件和源文件指向完全相同的 Chunk 地址。

四、Master 节点的操作

    1. Master 节点作用
        a.执行所有的名称空间操作。
        b.管理整个系统所有 Chunk 副本,主要包括决定 Chunk 存储位置、创建新 Chunk 及其副本、协调各种系统活动保证 Chunk 被完全复制、在所有 Chunk 服务器间进行负载均衡、回收不再使用的存储空间等。
    
    2. 名称空间管理和锁
        a.名称空间
            在逻辑上,GFS 的名称空间是一个全路径的元数据映射关系的查找表(利用前缀压缩,存储在内存),在存储命名空间的树形结构上,每个节点(绝对路径的文件名或绝对路径的目录名)都有一个关联的读写锁,允许同时进行多个操作,使用名称空间 region 上的锁保证执行顺序。
        b.锁:对 Master 节点的操作开始前都要获得一系列的锁。
            I. 例子:/home/user 被快照到 /save/user,防止创建 /home/user/foo;
            II. 过程:通过快照操作获取 /home 和 /save 的读取锁,/home/user 和 /save/user 的写入锁;文件创建获得 /home 和 /home/user 的读取锁,/home/user/foo 的写入锁。这两个步骤顺序执行(原因:都获取 /home/user 的锁是冲突的);
            III. 锁的优点:支持对同一目录的并行操作;文件名的读取锁防止父目录被删除、改名、被快照;文件名的写入锁序列化文件创建操作,保证不会多次创建同名文件;
            IV. 惰性分配策略:多个节点不用时立刻删除;全局一致顺序避免死锁。
    
    3. 副本的位置
        a.目标:最大化数据可靠性、可用性;最大化网络带宽利用率;
        b.措施:多个机架间分布存储 Chunk 的副本;
        c.特点:读操作有效利用多个机架整合带宽;写操作必须和多个机架上的设备网络通信。

    4. 创建、重新复制、重新负载均衡(Chunk 副本的用途)
        a.创建
            I. Master 节点选择放置新建的 Chunk 的空的副本;
            II. 考虑因素:
                在低于平均硬盘使用率的 Chunk 服务器上存储新的副本,平衡硬盘使用率;
                限制每个 Chunk 服务器上“最近”的 Chunk 创建操作的次数(防止多次写操作);
                把 Chunk 副本分布在多个机架之间。
        b.重新复制
            I. 触发条件:Chunk 的有效副本数量少于用户指定的复制因数;
            II. 原因:一个 Chunk 服务器不可用,一个副本损坏,Chunk 副本的复制因数提高了;
            III. 排序:
                每个要被重新复制的 Chunk 会根据以下几个因素排序:
                Chunk 现有副本数量和复制因数差多少。差的多的比差的少的优先级高;
                优先重新复制活跃文件的 Chunk 而不是刚被删除的文件的 Chunk;
                为了最小化失效 Chunk 对正在运行的应用程序的影响,提高会阻塞客户机程序处理流程的 Chunk 的优先级。
            IV. 实际操作
                选择优先级最高的 Chunk,命令某个 Chunk 服务器从可用的副本克隆一个新副本;
                防止克隆时产生的网络流量大大超过客户机流量,Master 节点限制同时进行克隆操作的数量;
                Chunk 服务器调节对源 Chunk 服务器读请求的频率限制克隆操作的带宽。
        c.重新负载均衡
            I. Master 服务器周期性对副本进行负载均衡,检查当前副本情况;
            II. Master 服务器逐渐填满一个新的 Chunk 服务器,而不是短时间内填满防止过载;
            III. Master 节点选择哪个副本要被移走(一般一走剩余空间低于平均值的 Chunk 服务器上的副本)。

    5. 垃圾回收
        a.机制
            GFS 在文件删除后不会立刻回收可用的物理空间。GFS 空间回收采用惰性的策略,只在文件和 Chunk 级的常规垃圾收集时进行。
            回收步骤如下:
            I. Master 节点记录删除操作日志;
            II. Master 节点修改文件名为一个包含删除时间戳的、隐藏的名字;
            III. Master 节点常规扫描文件系统命名空间时删除所有三天前的隐藏文件,此时仍可以用新的特殊名字读取;或把隐藏文件改名为正常显示的文件名的方式“反删除”;
            IV. 当隐藏文件从名称空间中删除,Master 服务器内存中保存的这个文件的元数据才会被删除,切断文件和所有 Chunk 的连接;
            V. 对 Chunk 名字空间常规扫描时,Master 节点找到不被任何文件包含的 Chunk 并删除其元数据。Chunk 服务器在和 Master 节点交互的心跳信息中,报告它拥有的 Chunk 子集的信息,Master 节点回复 Chunk 服务器哪些 Chunk 在 Master 节点保存的元数据中已经不存在了,Chunk 服务器可以任意删除这些 Chunk 的副本。
        b.讨论
            Chunk 的所有引用都只存储在 Master 服务器上的文件到块的映射表中,Chunk 的所有副本都以Linux文件的形式存储在Chunk服务器的指定目录下;
            相比直接删除的优势:提供了一致的、可靠的清除无用副本的方法;垃圾回收把存储空间的回收操作合并到 Master 节点规律性的后台活动中,在空闲时间完成,应答效率高;延缓存储空间回收为意外的、不可逆转的删除操作提供了安全保障。

    6. 过期失效的副本检测
        a.Master 节点保存了每个 Chunk 的版本号,用来区分当前的副本和过期副本;
        b.Master 节点以当前更高的 Chunk 版本号为准;
        c.Master 节点在例行的垃圾回收过程中移除所有的过期失效副本,客户机或者 Chunk 服务器在执行操作时都会验证 Chunk 的版本号以确保总是访问当前版本的数据。

五、容错和诊断

    1.高可用性
        a.快速恢复被设计为可以在数秒钟内恢复它们的状态并重新启动;
        b.Chunk 复制:每个 Chunk 都被复制到不同机架上的不同的 Chunk 服务器上;用户可以为文件命名空间的不同部分设定不同的复制级别。
        c.Master 服务器的复制:
            I. Master 服务器所有的操作日志和checkpoint 文件都被复制到多台机器上;
            II. 对 Master 服务器状态的修改操作能够提交成功的前提是操作日志写入到 Master 服务器的备节点和本机的磁盘;
            III. “影子”Master 服务器,这些“影子”服务器在“主”Master 服务器宕机的时候提供文件系统的只读访问,它们是影子,而不是镜像,所以它们的数据可能比“主”Master 服务器更新要慢。
    
    2.数据完整性
        a.每个 Chunk 服务器都使用与独立维护 Checksum 来检查与校验保存的数据或副本的完整性;
        b.每个 Chunk 都分成 64KB 大小的块。每个块都对应一个 32 位的 Checksum,和其它元数据一样,Checksum 与其它的用户数据是分开的,并且保存在内存和硬盘上,同时也记录操作日志;
        c.在 Chunk 服务器空闲的时会扫描和校验每个不活动的 Chunk 的内容。一旦发现有 Chunk 的数据损坏,Master 可以创建一个新的、正确的副本,然后把损坏的副本删除掉。
    
    3.诊断工具包括:诊断日志;RPC 日志包含了网络上发生的所有请求和响应的详细记录,但是不包括读写的文件数据。

六、度量

    注:此部分中包括多处 Google 内部使用的真实的 GFS 集群的基准数据,如需详细了解可查询原文,此处仅归纳总结。

    1.小规模基准测试
        a.读取:当读取的客户机增加时,多个客户机同时读取一个 Chunk 服务器的几率也增加了,导致整体的读取效率下降。
        b.写入:多个客户机并行写入可能引起的冲突比多个客户机并行读取要大得多,因为每个写入都会涉及三个不同的副本,写入的速度比我们想象的要慢。
        c.记录追加:
            记录追加操作的性能受限于保存文件最后一个 Chunk 的 Chunk 服务器的带宽,而与客户机的数量无关。
            记录追加的速度随客户机个数的增加而降低,主要是由于不同客户端的网络拥塞以及网络传输速度的不同而导致。
    
    2.实际应用中的集群
        a.存储:“死文件”是指文件被删除了或者是被新版本的文件替换了,但是存储空间还没有来得及被回收。
        b.元数据:
            大多数文件的元数据都是以前缀压缩模式存放的文件名;
            每一个 Chunk 都保存了当前的副本位置以及对它的引用计数,用于实现写时拷贝(即 COW,copy-on-write);
            Master 服务器上存放的其它元数据包括了文件的所有者和权限、文件到 Chunk 的映射关系,以及每一个 Chunk 的当前版本号;
            对于每一个单独的服务器,包括 Chunk 与 Master 服务器,都只保存了 50MB 到 100MB 的元数据。
        c.读写速率:读取速率要比写入速率高的多,在总的工作负载中,读取的比例远远高于写入的比例。
        d.Master 服务器的负载:Master 服务器通过对名字空间进行二分查找来提高效率。
        e.恢复时间:
            当某个 Chunk 服务器失效了,一些 Chunk 副本的数量可能会低于复制因子指定的数量,我们必须通过克隆副本使 Chunk 副本数量达到复制因子指定的数量;
            恢复所有 Chunk 副本所花费的时间取决于资源的数量。
    
    3.工作负荷分析
        a.方法论和注意事项:从 GFS 服务器记录的真实的 RPC 请求日志中推导重建出关于 IO 操作的统计信息;
        b.Chunk 服务器工作负荷:
            I. 读取操作:小的读取操作(小于 64KB)一般是由查找操作的客户端发起的,目的在于从巨大的文件中查找小块的数据;大的读取操作(大于 512KB)一般是从头到尾顺序的读取整个文件;
            II. 写入操作:大的写操作(超过 256KB)通常是由于 Writer 使用了缓存机制;Writer 缓存较小的数据,通过频繁的 Checkpoint 或者同步操作,或者只是简单的统计小的写入的数据量,之后批量写入;
            III. 涉及的数据量均呈现双峰分布。
        c.记录追加 vs 写操作
            数据修改操作主要是记录追加操作而不是覆盖方式的写操作;
            覆盖写操作,大部分是由于客户端在发生错误或者超时以后重试的情况。这在本质上应该不算作工作负荷的一部分,而是重试机制产生的结果。
        d.Master 的工作负荷
            大部分的请求都是读取操作查询 Chunk 位置信息(FindLocation)、以及修改操作查询 lease 持有者的信息(FindLease-Locker)。

七、经验

    1. 需要更多的基础架构来防止用户间的相互干扰。 

    2. 最大的问题是磁盘以及和 Linux 相关的问题。
            I. 在使用 Linux 2.2 内核时遇到了些问题,主要是 fsync()的效率问题,它的效率与文件的大小而不是文件修改部分的大小有关。这在我们的操作日志文件过大时给出了难题,尤其是在我们尚未实现 Checkpoint 的时候。我们费了很大的力气用同步写来解决这个问题,但是最后还是移植到了 Linux2.4 内核上。 

           II. 单个读写锁的问题,也就是说,在某一个地址空间的任意一个线程都必须在从磁盘 page in(读锁)的时候先 hold 住,或者在 mmap()调用(写锁)的时候改写地址空间。我们发现即使我们的系统负载很轻的情况下也会有偶尔的超时,我们花费了很多的精力去查找资源的瓶颈或者硬件的问题。最后我们终于发现这个单个锁在磁盘线程交换以前映射的数据到磁盘的时候,锁住了当前的网络线程,阻止它把新数据映射到内存。由于我们的性能主要受限于网络接口,而不是内存 copy 的带宽,因此,我们用 pread()替代 mmap(),用了一个额外的 copy 动作来解决这个问题。  

        III. 尽管偶尔还是有其它的问题,Linux 的开放源代码还是使我们能够快速探究和理解系统的行为。在适当的时候,我们会改进内核并且和公开源码组织共享这些改动。 

八、相关工作

    1. GFS 提供了一个与位置无关的名字空间,这使得数据可以为了负载均衡或者灾难冗余等目的在不同位置透明的迁移。

    2. GFS 目前只使用复制的方式来进行冗余,需要更多的裸存储空间。

    3. GFS 并没有在文件系统层面提供任何 Cache 机制。
        我们主要的工作在单个应用程序执行的时候几乎不会重复读取数据,因为它们的工作方式要么是流式的读取一个大型的数据集,要么是在大型的数据集中随机 Seek 到某个位置,之后每次读取少量的数据。

    4. 由于处于中心位置的 Master 服务器保存有几乎所有的 Chunk 相关信息,并且控制着 Chunk 的所有变更,极大地简化了原本非常复杂的 Chunk 分配和复制策略的实现方法。

    5. 我们通过减少 Master 服务器保存的状态信息的数量,以及将 Master 服务器的状态复制到其它节点来保证系统的灾难冗余能力。

    6. 扩展能力和高可用性(对于读取)目前是通过我们的影子 Master 服务器机制来保证的。对 Master 服务器状态更改是通过预写日志的方式实现持久化。

    7. 我们通过原子的记录追加操作实现了生产者-消费者队列,GFS 采用可以被生产者并发追加记录的持久化的文件的方式实现。GFS 只支持 m-到-1 的队列。多个消费者可以同时读取一个文件,但是它们输入流的区间必须是对齐的。

    8. Google 文件系统展示了一个使用普通硬件支持大规模数据处理的系统的特质。虽然一些设计要点都是针对我们的特殊的需要定制的,但是还是有很多特性适用于类似规模的和成本的数据处理任务。 

九、结束语

    注:结束语作为文章的总结部分,原文如下。

    首先,我们根据我们当前的和可预期的将来的应用规模和技术环境来评估传统的文件系统的特性。我们的评估结果将我们引导到一个使用完全不同于传统的设计思路上。根据我们的设计思路,我们认为组件失效是常态而不是异常,针对采用追加方式(有可能是并发追加)写入、然后再读取(通常序列化读取)的大文件进行优化,以及扩展标准文件系统接口、放松接口限制来改进整个系统。 

    我们系统通过持续监控,复制关键数据,快速和自动恢复提供灾难冗余。Chunk 复制使得我们可以对 Chunk 服务器的失效进行容错。高频率的组件失效要求系统具备在线修复机制,能够周期性的、透明的修复损坏的数据,也能够第一时间重新建立丢失的副本。此外,我们使用 Checksum 在磁盘或者 IDE 子系统级别检测数据损坏,在这样磁盘数量惊人的大系统中,损坏率是相当高的。 

    我们的设计保证了在有大量的并发读写操作时能够提供很高的合计吞吐量。我们通过分离控制流和数据流来实现这个目标,控制流在 Master 服务器处理,而数据流在 Chunk 服务器和客户端处理。当一般的操作涉及到 Master 服务器时,由于 GFS 选择的 Chunk 尺寸较大(alex 注:从而减小了元数据的大小),以及通过 Chunk Lease 将控制权限移交给主副本,这些措施将 Master 服务器的负担降到最低。这使得一个简单、中心的 Master 不会成为成为瓶颈。我们相信我们对网络协议栈的优化可以提升当前对于每客户端的写入吞吐量限制。 

    GFS 成功的实现了我们对存储的需求,在 Google 内部,无论是作为研究和开发的存储平台,还是作为生产系统的数据处理平台,都得到了广泛的应用。它是我们持续创新和处理整个 WEB 围内的难题的一个重要工具。 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值