常见 MQ 的比较 - Kafka、RocketMQ、RabbitMQ的优劣势比较 GFS 论文学习和 HDFS 实现的比较 Docker技术入门与实战 - 使用 dockerfile定制镜像 I love log 读书笔记 flink 入门程序-wordcount flink 配置项介绍 在 Mac 上搭建 Flink 的开发环境 lambda 架构问题的阅读笔记 IDEA常用插件 Mybatis源码分析(1) - Mybatis关键类 Mybatis源码分析(1) - Mybatis包目录简介 tair 1:tair学习 dataflow论文阅读笔记 Polysh的安装使用 SnappyData排序函数比较 Squirrel-sql客户端连接SnappyData手册 在虚拟机里显示Hello World spark学习博客推荐 SnappyData学习博客和官网文章 Docker常用命令 MyBatis支持的OGNL语法 mysql性能优化 mysql性能优化-优化Sql语句 java各版本新特性 mac上命令行操作 explain输出格式 从文件中读取zk配置——ZooKeeper编程技能(1) git进阶经验-从项目中删除移除的目录 Mongodb 学习之shell命令操作(3) mysql命令 git进阶经验-从多模块项目中分理子模块 从零学hadoop-搭建基础(单点)的Hdfs环境 ZooKeeper集群操作脚本 Vue安装使用 2 初学JVM之问答式记住类加载机制 2 初学JVM之问答式记住虚拟机性能监控与故障处理工具 2 初学JVM之问答式记住垃圾收集器 log4j2 按天生成日志文件 1 初学JVM之问答式记住java自动内存管理 MapReduce学习心得之MapReduce初识 log4j2 日志发送到kafka配置实战 log4j2 日志配置实战 Mongodb 学习之shell命令操作(二) Mongodb 学习之linux版本安装(一) Dubbo的初级使用 ServiceLoader内部实现分析 ServiceLoader 初级应用 log4j日志发送邮件配置实战 红黑树笔记 IDEA首次使用之前的配置 java源码学习之Enum java源码学习之String 自定义Spring tag标签 编写一键发布脚本 记一次Spring Scheduler莫名不执行的一次堆栈分析 kafka的基本操作 nginx 5:Nginx内部变量 nginx 4:Nginx日志管理 提高hadoop配置效率的shell脚本 Hive编程指南之一 Hive的安装 Ambari服务器安装 Ambari服务器管理集群 HBase分布式安装 windows下Eclipse远程调试运行MR程序 基于MapReduce新的API的编程Demo-wordCount window下Eclipse远程只读HDFS上的文件 YARN上节点标签 编写第一个MapReduce的wordcount程序 NodeManager的重启 搭建JStorm集群 YARN上的web应用代理 YARN上的ResourceManager的高可用方案 配置vmware中的虚拟机使用宿主机的共享网络 YARN架构简述 HDFS 架构 Spring的统一异常处理机制 Tomcat 配置服务 HDFS的viewfs指南 HDFS的Federation之路 HDFS基于QJM的HA之路 nginx 3:Nginx反向代理 mybatis操作主体流程 1.正则表达式学习-基础篇 log4j日志配置详解 mysql的时间函数 nginx 2:Nginx模块配置理论及实战 HashMap相关解析和测试文章 工作一年后的面试 用私有构造器或枚举类型强化Singleton属性 java中比较重要的图 mybatis处理枚举类 mybatis集成进spring Spring比较重要的几个截图 21.hadoop-2.7.2官网文档翻译-使用NFS的HDFS高可用性 20.hadoop-2.7.2官网文档翻译-使用仲裁日志管理器的HDFS高可用性 markdown在jekyll中支持的一些操作 Spring项目中配置sl4j和log4j的日志配置 19.hadoop-2.7.2官网文档翻译-HDFS命令指南 Spring的profile机制介绍 mybatis-generator反向生成 18.hadoop-2.7.2官网文档翻译-HDFS用户指南 17.hadoop-2.7.2官网文档翻译-实现Hadoop中Dapper-like追踪 16.hadoop-2.7.2官网文档翻译-Hadoop的KMS(key 管理服务器)-文档集 15.hadoop-2.7.2官网文档翻译-Hadoop的http web认证 14.hadoop-2.7.2官网文档翻译-服务级别的授权指南 13.hadoop-2.7.2官网文档翻译-安全模式中的Hadoop 09.hadoop-2.7.2官网文档翻译-Hadoop命令行微型集群 12.hadoop-2.7.2官网文档翻译-机架感知 11.hadoop-2.7.2官网文档翻译-代理用户-超级用户对其他用户的代表 10.hadoop-2.7.2官网文档翻译-原生库指南 08.hadoop-2.7.2官网文档翻译-文件系统规范 07.hadoop-2.7.2官网文档翻译-Hadoop接口类别 (转)浅析 Decorator 模式,兼谈 CDI Decorator 注解 06.hadoop-2.7.2官网文档翻译-Hadoop的兼容性 05.hadoop-2.7.2官网文档翻译-文件系统命令 04.hadoop-2.7.2官网文档翻译-Hadoop命令指南 03.hadoop-2.7.2官网文档翻译-集群安装 02.hadoop-2.7.2官网文档翻译-单节点集群安装 01.hadoop-2.7.2官网文档翻译-概述 Http 协议相应状态码大全及常用状态码 IDEA快捷键 JDBC Type与Java Type redis 12:redis 操作集合 mybatis-generator错误集合 redis 11:redis 错误集合 nginx 1:nginx的安装 redis 10:redis cluster命令操作 redis 9:redis实例集群安装 java设计模式 hadoop集群学习笔记(1) Apache Shiro 简介 vim编辑神器的进阶命令 Eclipse配置 Eclipse快捷键 Linux 测试题 Linux脚本学习(1) Linux启动简要过程 Centos7上安装Mysql hadoop集群学习笔记(1) (转)分布式发布订阅消息系统 Kafka 架构设计 maven 命令 Kafka集群安装 Kafka初步使用 redis 8:redis server 和 scripting命令操作 redis 7:redis transaction 和 connection命令操作 redis 6:redis hash 命令操作 redis 5:redis sorted_set 命令操作 搭建本地Jekyll+Markdown+Github的开发环境 Spring源码阅读笔记(2) redis 4:redis set命令操作 Spring添加任务调度配置 redis 3:Redis list命令操作 redis 2:redis 一般命令操作 redis 1:redis单机安装笔记 redis 0:redis配置属性描述 Spring源码阅读笔记(1) spark 错误集锦 spark集群安装 Linux 基本命令操作 Hadoop错误信息处理 Hadoop代码拾忆 从零开始搭建spring-springmvc-mybatis-mysql和dubbo项目 java知识点札记 java排错 Google Java Style 中文版 git进阶经验 github使用经验 MongoDB用户角色授权与AUTH启用 MongoDB 命令 MongoDB 特定规范 Spring MVC实现跳转的几种方式 史上最全最强SpringMVC详细示例实战教程 Spring 零星笔记 js中(function(){…})()立即执行函数写法理解 如何解决跨域问题 创建ajax简单过程 前端定位 设置MYSQL允许通过IP访问 mybatis异常 :元素内容必须由格式正确的字符数据或标记组成 如何为 WordPress 绑定多个域名的方法s WordPress工作原理之程序文件执行顺序(传说中的架构源码分析) Spring源码导入Eclipse中 基于PHPnow搭建Eclipse开发环境 解决wordpress首页文章内容截断处理的几种方法 ZooKeeper理论知识 ZooKeeper集群安装配置 Git常用命令速查表 Linux 4:磁盘与文件系统管理 Linux 3:文件与目录管理 Linux 2:文件权限与目录配置 Markdown输入LaTeX数学公式
从零学hadoop-搭建基础(单点)的Hdfs环境 MapReduce学习心得之MapReduce初识 Ambari服务器安装 Ambari服务器管理集群 windows下Eclipse远程调试运行MR程序 基于MapReduce新的API的编程Demo-wordCount window下Eclipse远程只读HDFS上的文件 YARN上节点标签 编写第一个MapReduce的wordcount程序 NodeManager的重启 YARN上的web应用代理 YARN上的ResourceManager的高可用方案 YARN架构简述 HDFS 架构 HDFS的viewfs指南 HDFS的Federation之路 HDFS基于QJM的HA之路 21.hadoop-2.7.2官网文档翻译-使用NFS的HDFS高可用性 20.hadoop-2.7.2官网文档翻译-使用仲裁日志管理器的HDFS高可用性 19.hadoop-2.7.2官网文档翻译-HDFS命令指南 18.hadoop-2.7.2官网文档翻译-HDFS用户指南 17.hadoop-2.7.2官网文档翻译-实现Hadoop中Dapper-like追踪 16.hadoop-2.7.2官网文档翻译-Hadoop的KMS(key 管理服务器)-文档集 15.hadoop-2.7.2官网文档翻译-Hadoop的http web认证 14.hadoop-2.7.2官网文档翻译-服务级别的授权指南 13.hadoop-2.7.2官网文档翻译-安全模式中的Hadoop 09.hadoop-2.7.2官网文档翻译-Hadoop命令行微型集群 12.hadoop-2.7.2官网文档翻译-机架感知 11.hadoop-2.7.2官网文档翻译-代理用户-超级用户对其他用户的代表 10.hadoop-2.7.2官网文档翻译-原生库指南 08.hadoop-2.7.2官网文档翻译-文件系统规范 07.hadoop-2.7.2官网文档翻译-Hadoop接口类别 06.hadoop-2.7.2官网文档翻译-Hadoop的兼容性 05.hadoop-2.7.2官网文档翻译-文件系统命令 04.hadoop-2.7.2官网文档翻译-Hadoop命令指南 03.hadoop-2.7.2官网文档翻译-集群安装 02.hadoop-2.7.2官网文档翻译-单节点集群安装 01.hadoop-2.7.2官网文档翻译-概述 hadoop集群学习笔记(1) hadoop集群学习笔记(1) Hadoop错误信息处理 Hadoop代码拾忆

GFS 论文学习和 HDFS 实现的比较

2019年08月20日
摘要:

论文及翻译

GFS原文Paper

GFS 的中文翻译版本

学习笔记

GFS paper 学习

设计概要

GFS 与以往分布式文件系统的不同点

  1. 容错性。 部分错误不再被当错异常,而是视为常见情况处理。实时地监控、错误检测、容错、自动恢复对系统来说必不可少。
  2. 面向大文件存储, 几个 GB 或更大。TB 甚至 PB 规模的数据集时,传统的 KB级别大小(现有如 NTFS 等文件系统的文件块大小)的文件块很难管理,必须重新设计。做到对大文件高效,对小文件支持但不做优化。
  3. 一次写多次读。 通过添加新数据完成更新操作,而不是更改已有数据。因为文件比较大,客户机不做缓存。而添加操作成为性能优化和原子性保证的焦点
  4. 两种读操作
    1. 大量数据的流式读。同一客户端的连续操作通常读文件的连续区域
    2. 少量数据的随机读。性能敏感的对少量数据读操作分类并批量处理。
  5. 大量数据的连续写。也支持少量数据的随机写,但不必高效。
  6. 支持同一文件的多用户并发写的添加操作语义。

系统接口

GFS 提供了相似的文件系统界面,但没有实现标准的 POSIX 的 api

体系结构

GFS 架构图

各节点介绍
  1. GFS master :
    1. 维护文件系统的元数据(metadata),包括命名空间、访问控制信息、文件到块的映射和块的当前位置。
    2. 负责系统的集中调度: chunk 租约管理,孤儿块的垃圾收集,chunkserver 间的块迁移。
    3. 与 chunkserver 定期 heartBeat,给 chunkserver 传递指定和收集其状态。
  2. GFS chunkserver: GFS 的数据存储节点。一个文件会被分为多个固定大小的 chunk(默认 64M),每个 chunk 有全局唯一句柄,64 位的 chunkId。每个 chunk会被复制到多个 chunkserver 上,做数据冗余,保证可靠性。
  3. GFS client: 嵌入在应用代码中与 GFS 服务端(master 和 chunkserver)通信代表应用来读写数据。client 只与 master 沟通数只限于数据存储的元数据。而数据的读写交换是与 chunkserver 进行的。client 不缓存文件数据,但是会缓存与 master 交互的元数据。

客户端和 chunkserver不缓存文件数据,因为文件内容可能太大而无法缓存。

单 master

单 master 可以简化设计并使得 master 可以根据全局情况作出先进的块放置和复制决定。因此master 要尽量少的参与读写交互,避免成为系统瓶颈。由此就会有主 chunkserver 的租约机制

读操作流程

  1. client使用固定的块大小将应用程序指定的文件名和字节偏移转换成文件的一个块索引(chunk index)
  2. client 给master发送一个包含文件名和块索引的请求
  3. master回应对应的chunk handle和副本的位置(多个副本)。
  4. client以文件名和块索引为键缓存这些信息。(handle和副本的位置)
  5. Client 向其中一个副本发送一个请求,指定chunk handle和块内的一个字节区间。

除非缓存信息失效或文件被重新打开,否则 client 对同一个块的请求不再与 master 交互

块规模

选择使用较大的块(64M),hdfs 中默认 256M,可以减少 master 存储的元数据的大小。

好处:

  1. 减少 client 与 master 的交互。
  2. client可能有多个操作,与 chunkserver 保持较长 tcp 连接可减少网络负载。
  3. 减少 master 上的元数据规模。

元数据

master 中存储了三种元数据

  1. 文件的命名空间和块的命名空间
  2. 从文件到块的映射
  3. 块的副本的位置

前两种元数据通过向操作日志等级修改而保持不变,操作日志在远程机器上,如 NFS 上有副本。使用日志可以简单可靠的更新 master 状态并在 master宕机后保持一致性。

三种数据

  1. 内存数据结构: 元数据存储在内存中,master 可以快速响应和高效的在后台扫描整个状态。扫描主要实现垃圾收集、chunkserver 出现问题时的副本复制,为平衡负载和磁盘空间做的块迁移。 这种方式的瓶颈在 master 的内存大小。因块设置的足够大,且块的元数据很小(64字节)。即使集群扩大,只需要适当增加 master 的内存。简单高效,代价小。
  2. 块位置 master 中保存的块副本的位置不是一成不变的,因为 chunkserver 机器随时都有可能加入或宕机, 因此其块的位置也是随时动态变化的。
  3. 操作日志 操作日志包含了对元数据所做的修改的所有历史记录。以其作为逻辑时间线定义了并发操作的实际顺序。 因为操作日志的重要性,系统只有将日志持久化到本地或远程机器上才会响应用户请求。

一致性模型

GFS 架构图

  1. 文件的命名空间的修改必须是原子性的,只能由 master 操作。命名空间锁保证原子性和正确性。master 的操作日志定义的全局唯一的操作顺序。
  2. 文件区间的状态在修改后依赖于修改的类型 非并发写操作对影响的区域是已定义的。 成功的并发写操作是未定义但是一致的。 失败的修改将会使区间处于不一致的状态。
  3. 成功操作后,最后的修改操作保证文件区域是已定义的。GFS 对所有副本执行同样顺序的同样操作,并使用块版本号检查过时的副本。
  4. 修改操作后,可能故障导致数据不完整。GFS 通过 master 和 chunkserver 进行 handshake,借助校验来检测对数据的破坏。在 GFS 定期检测前,所有副本都失效,则该数据块丢失。

系统交互

租约和修改顺序

修改(write 和 record append)会更改 chunk 上所有副本上执行。通过租约保证副本上的修改顺序的一致性。

master 节点会在所有副本中选择一个 chunk 为其授权租约,我们将其称为primary,主块。该主块主要是为该块上所有的修改设定顺序序号。所有的其他副本都会应用该更改顺序。因此,全局修改序列首先由master 节点选择的租赁授权顺序定义,并在租约内由主块分配的序列号定义。

租约是为了减轻 master 的负担,防止其称为系统瓶颈。

授权期限初始化为 60s,主块可以在失效前主动从 master 申请延期。

master 和所有的 chunkserver 之间都是通过心跳消息完成授权的申请和赋权。

如果主块的文件改名了,master 会在租约到期前重新给该块授权租约。 如果该块失效了。那么master 都在授权到期后,重新将租约授权给该块其他正常的副本。

数据更改流程

  1. 客户端请求 master,询问持有租约的chunk所在的chunkserver 及chunk 的其他副本信息。 如果请求的块及副本没有租约,则 master 指定其中一个副本并授权其租约
  2. master 回应客户端 primary即主块的 id,和其他副本的位置信息。客户端将这些信息缓存下来。除非primary的信息失效,否则客户端不再因为该块信息与 master 进行联系。
  3. 客户端链式的将数据推送到所有的副本,而每个 chunkserver 会将数据缓存在内部的 LRU 缓存中。通过将数据流与控制流分离,我们可以通过基于网络拓扑调度昂贵的数据流来提高性能,而不管哪个 chunkserver 是primary.
  4. 一旦数据在所有的副本写入后,客户端会给primary发送一个写请求。primary就会为这些改变分配连续的序列号。
  5. primary会同时将写请求推送到其他所有的副本上。每个副本都按照primary给定的顺序进行更改。
  6. 其他所有副本操作完成后,响应primary的通知,并回复已完成更改。
  7. primary回应客户端写入完成。 在写过程中,任何的其他副本写入错误都会通知客户端,然后客户端会再次做向 chunkserver 发数据做重试。直到重试成功或达到最大重试次数。

如果写入文件大小超过了一个 chunk 的边界,客户端就会将该操作切分为多个写操作。并执行上面的写入流程。

数据流

为了有效的利用网络,将控制流和数据流分开。

在控制流从客户端流向primary然后在流向其他副本时。数据流会找离客户端最近的chunkserver 机器以线性管道的方式将数据推到 chunkserver A 的链上,然后A 在接收到客户端推送的数据后,会立即向离其最近的未分发数据的 chunkserver B 上同步数据。

好处:

  1. 有效利用网络带宽传输数据
  2. 降低管道数据传输的时间延时。

数据传输时间计算(排除网络连接时间): time = B/T + RL

B : 传输数据的字节数 T : 网络带宽 R : 副本的数量 L : 两个副本间传输数据的延时情况

原子性 record append

GFS提供了原子追加的操作叫record append

record append在分布式应用中大量使用,不同机器的多个 client 会同时并发的 append 同一个文件。这种操作对于传统的 write 来说需要使用额外的、复杂的、开销比较大的锁。而这些文件在 GFS 工作中是以多生产者一个消费者队列方式或包含从多个不同客户端合并的数据结果。

如果记录在任何的副本中 append 失败,客户端都会进行重试。因此,相同的 chunk 副本可能包含不同的数据。GFS 不保证所有副本的字节数都是相同的。它只保证数据作为原子单位至少写入一次。

快照

快照操作几乎在瞬间构造一个文件和目录树的副本,同时将正在进行的其他修改操作对它的影响减至最小。

AFS类似,GFS 也是使用的copy-on-write机制来实现的快照。

过程:

  1. 当 master 接收到snapshot请求时,它首先撤销对即将snapshot的文件中的块的任何未决租约。这保证之后的任何需要写到这些 chunk 的操作都需要先于 master 交互来获得哪些 chunk 获取到了租约。这就给 master 了一个创造这个 chunk 的副本的机会。
  2. 当撤销租约或者租约过期后,master 会将该操作写入日志。
  3. 复制原文件或目录树的元数据以对他的内存状态实施登记的操作。新创建的 snapshot 文件和原文件指向相同的 chunk
  4. 在 snapshot 建立后,客户端第一次向chunk c写时,会发请求到 master以找到用友 lease 的副本。maste 注意到chunk C 的引用计数比 1 大后,master 会延迟对客户端的响应并选择一个chunk handle C,然后要求每一个有``chunk c副本的 chunkserver都创建一个新的chunk并命名为C`。每个 chunkserver 都是在本地创建 chunk c,这样就避免的网络的开销。

master 操作

主要工作:

  1. 所有的命名空间的操作。
  2. 整个系统的 chunk 复制。
    1. 制作安置决定
    2. 创建新的 chunk 和后续的副本。
    3. 协调各种系统范围内的活动,以便完全复制chunk、平衡整个系统的负载并回收未使用的存储。

命名空间管理和锁

  1. GFS 没有与每个目录相关的能列出其所有文件的数据结构,也不支持文件或目录的别名(类似于 UNIX 系统的硬链接和符号链接)。
  2. GFS 的命名空间逻辑上是文件的全路径名和元数据的映射的查用表。
  3. MASTER操作的并行性和数据的一致性就是通过这些锁来实现的。

master 在执行操作前会获取一系列的锁。比如,操作文件/d1/d2/.../dn/leaffile,会获取该文件所属的每一级目录的读锁,和目标文件上的写锁。 由于命名空间可以有许多节点,因此读写锁定对象会被懒惰地分配,并且一旦它们不被使用就会被删除。 此外,以一致的总顺序获取锁以防止死锁:它们首先按时间间隔树中的级别排序,并按字典顺序排列在同一级别内

副本放置策略

chunk副本的位置策略只有两个目的:

  1. 最大化数据的可用性和可靠性
  2. 最大化网络的带宽利用率。

不能将鸡蛋放在一个篮子里

对于副本的分配,为了避免机房或机架故障或断电离线等特殊情况。需要将每个 chunk 的副本分开放置。

  1. 同机架跨chunkserver 放置。数据放在同一机架的不同 chunkserver 机器节点上。
  2. 跨机架副本放置。数据放在同一机房,不同的机架上。
  3. 跨机房副本放置。数据放在同一地区的,不同机房内。
  4. 跨中心副本放置。数据放在同一城市地区的不同中心。比如北京中心 1,北京中心 2。
  5. 跨地域副本放置。数据方在不同的城市或国家。比如跨国公司数据跨城市、跨洲备份等。

数据的副本数量越多,数据备份就会被放置的越分散。

创建、重复制、重平衡机制

chunk 副本被创建的原因:

  1. chunk 被创建
  2. chunk 被重新复制
  3. 系统对 chunk 数据的重平衡

chunk 被创建考虑的因素

  1. 放置在磁盘利用率低的 chunkserver 上,平衡整个系统的磁盘利用率。
  2. 控制在一个 chunkserver 上新创建 chunk 的数量。
  3. 跨机架备份。

chunk 被重新复制的原因

  1. 服务器不可用
  2. 数据损坏
  3. 磁盘损坏
  4. 备份数目被修改

master 周期性平衡 chunkserver 的负载

  1. 检查 chunk 分布和负载均衡,通过该方式填充新的 chunkserver

垃圾收集

GFS 对于已删除的文件不会立即回收空间,它采用的是懒删除的机制。

机制

一旦一个文件被删除,删除日志会立刻被 master 记录下来。相对于立即释放资源,GFS 只是将删除的文件重命名并带上删除时间戳。在 master 上的常规扫描文件系统的命名空间时,会扫出所有的删除时间在 3 天(可配置)以上的文件并释放资源。 然后改 chunk 信息在内存中会被删除,失去与 chunk 的链接。

在常规删除操作执行前,被删除的文件会以隐藏的名字存在与命名空间和磁盘上,对于错误的操作,也可以进行恢复操作。类似于 windows 上的回收站功能。这些操作的信息是通过 master 和 chunkserver 的心跳信息交流的。

讨论

尽管分布式下的垃圾回收是个难题,但是 GFS 中实现非常简单。

  1. 它可以很容易的识别到 chunk 的所有引用。它们都在由master专门维护的存档目录中
  2. 可以很容易的识别所有 chunk 的副本。它们是每个分块服务器上指定目录下的Linux文件。

优点

  1. 在大规模分布式存储中非常可靠。chunk 在创建时有副本能成功而有的失败,master 会丢失失败副本的消息。而 master 和 chunkserver 提供了统一且可靠的方法来清除位置的chunk 版本。
  2. 通过 master 的常规扫描分批完成,成本摊销。而且只有当 master 空间时才这么做。
  3. 延迟删除提供了防止意外删除,不可恢复的防护网。使得意外删除的数据在短期内可以找回还原。

缺点

  1. 在集群存储紧张时,会阻碍用户对空间微调进行的努力。即用户删除了部分文件,但是空间仍然没有释放。

灵活 允许用户将不同的复制和回收策略应用于不同的命名空间中的不同部分。例如:可以设置用户删除文件后,文件立即物理删除也不可撤销。

过时数据探测

可能会因为 chunkserver 宕机或者对 chunk 上的某些改变丢失而导致数据过时。因此对每个 chunk,master 有chunk version number来区分最新数据和过时数据。

  1. master 在授权新的租期给 chunk 时,会升级版本号,并将该版本号告知 chunk 及其副本们。不管 chunkserver 重启或者上报 chunk 的信息,master 通过比对版本号都能检测出过时的 chunk。

常规删除程序的作用

  1. 删除未知版本的数据。即chunk 副本同步失败的数据。
  2. 删除被标记为删除的数据,即延时删除的数据。
  3. 删除过时的数据。通过版本号区分最新数据和过时数据。

容错和诊断

高可用

快速恢复

master和 chunkserver 都被设计在数秒内就可以重启并恢复数据。

chunk 副本

每个 chunk 会建立多个副本,默认 3 个。副本放置在不同的机架上。

master副本

master 的副本。是将 master 的日志和检查点数据复制到多个机器上。每次修改都会将日志记录在 master 本地和其所有的副本存储上。

即使 mater 宕机了,shadowmaster 也可以提供提供只读的访问服务。

数据完整性

每个数据块服务器都利用校验和来检验存储数据的完整性。每个Chunk按64kB的大小分成块,每个块有32位的校验和,校验和和日志存储在一起,和用户数据分开。

相反,如果是覆盖现有数据的写,在写以前,我们必须检查第一和最后一个数据块,然后才能执行写操作,最后计算和记录校验和。如果我们在覆盖以前不先检查首位数据块,计算出的校验和则会因为没被覆盖的数据而产生错误。

在空闲时间,服务器会检查不活跃的数据块的校验和,这样可以检查出不经常读的数据的错误。一旦错误被检查出来,服务器会拷贝一个正确的数据块来代替错误的

诊断工具

广泛而细致的诊断日志以微小的代价换取了在问题隔离、诊断、性能分析方面起到了重大的作用。GFS服务器用日志来记录显著的事件(例如服务器停机和启动)和远程的应答。远程日志记录机器之间的请求和应答,通过收集不同机器上的日志记录,并对它们进行分析恢复,我们可以完整地重现活动的场景,并用此来进行错误分析

GFS 脑图

GFS 脑图

参考文献

典型分布式系统分析: GFS