<commit_before>---
layout: post
title:  GFS 论文学习和 HDFS 实现的比较
category: 技术
tags: BigData
keywords: 
description: 
---
 
{:toc}

# 论文翻译

[GFS 的中文翻译版本](https://blog.csdn.net/xuleicsu/article/details/526386)

# 学习笔记

## GFS paper 学习

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

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


### 系统接口

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

### 体系结构

![GFS 架构图](//raw.githubusercontent.com/George5814/blog-pic/master/image/hdfs/gfs-arch.png)

#### 各节点介绍

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 连接可减少网络负载。





<commit_msg>暂存对 gfs 的 paper 的笔记<commit_after>---
layout: post
title:  GFS 论文学习和 HDFS 实现的比较
category: 技术
tags: BigData
keywords: 
description: 
---
 
{:toc}

# 论文翻译

[GFS 的中文翻译版本](https://blog.csdn.net/xuleicsu/article/details/526386)

# 学习笔记

## GFS paper 学习

### 设计概要

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

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




#### 系统接口

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

#### 体系结构

![GFS 架构图](//raw.githubusercontent.com/George5814/blog-pic/master/image/hdfs/gfs-arch.png)

##### 各节点介绍

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 架构图](//raw.githubusercontent.com/George5814/blog-pic/master/image/hdfs/gfs-chunk-1.png)

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 都在授权到期后，重新将租约授权给该块其他正常的副本。


![数据更改流程](//raw.githubusercontent.com/George5814/blog-pic/master/image/hdfs/data-mutation-flow.png)

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 发数据做重试。直到重试成功或达到最大重试次数。

#### 数据流


#### 原子性记录追加

#### 快照

### master 操作

#### 命名空间管理和锁

#### 副本放置策略

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

#### 垃圾收集


#### 过时数据探测

### 容错和诊断





{'fraction_non_alphanumeric': 0.10375816993464053, 'fraction_numerical': 0.018137254901960786, 'mean_word_length': 6.401451027811366, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1884226', 'n_tokens_mistral': 4591, 'n_tokens_neox': 5282, 'n_words': 466}