GFS--Google File System论文翻译和理解

一、系统设计目标

高可用的大文件分布式文件系统。

二、关键点

  1. Architecture-架构:有哪些Server,每个Server的功能。
  2. Master存储的MetaData的结构。
  3. client写数据流程。
  4. client读数据流程。
  5. 启动时Master和ChunkServer的交互。
  6. ChunkServer发生故障时,Master和ChunkServer的交互。

三、核心设计概述

2. Master中存储的MetaData
class ChunkServer { // ChunkServer在Master中的数据结构
  string host; // ip+port信息 回复给client 用于数据读取
  int64  lastHeartBeat; // 上一次心跳的时间戳
}

map chunkSvrInfo; // chunkSvrId ==> ChunkServer

class Chunk { // 文件中数据块的数据结构
  int64 handleId; // 该数据块的唯一标识Id
  list chunkSvrId; // 存储该数据块的chunkSvrId
  int64 checkSum; // 该数据块checksum的结果 客户端读取数据时可根据checkSum校验读取的数据是否被破坏 不一定存在Master中 可在ChunkServer中
}

class File { // NameSpace中文件的数据结构定义
  string name; // 文件名
  vector chunks; // 顺序存储的chunk数据 
  int64 createTime;
  int64 updateTime;
}
class Directory { // NameSpace中目录的数据结构定义
  map  dirs; // 该目录下的所有子目录
  map files; // 该目录下的所有文件
}

// handleId到具体Chunk的映射关系 ChunkServer只存储了Chunk对应的handleId 
// 数据迁移时需要根据handleId找到对应的Chunk做出修改
map handleMap; 

Master持久化MetaData时,不会包含ChunkServer相关的信息,在Master和ChunkServer启动时通过HeartBeat获取ChunkServer的相关信息。

3. 一致性模型

consistent:all clients will always see the same data, regardless of which replicas they read from。// 所有client读的数据是一致的
defined:consistent and clients will see what the mutation writes in its entirety。// 修改最终会生效
Q1:写文件时,如何做数据块合并,即最后一个chunk没有写满,如何追加到这最后一个chunk。
Q2:写数据时,需要同时修改Master中的Meta信息和ChunkServer中的chunk信息,如何同步?
Q3:并发写数据时,如何做同步,即需要等前面的写完以后才开始写后面的数据吗?如果不这样,中间的写失败了如何处理?
Q4:并发append为什么会导致duplicate?
Q5:并发write和append的区别是什么?

四、系统交互

4.1 系统交互类型
  1. 写数据。
  2. 读数据。
  3. 删除、移动和拷贝。
4.2 锁机制

对文件进行并发交互时,冲突会导致数据的不确定,因此需要加锁。锁分为读写锁,并且针对绝对路径加锁,规则如下:
路径:/dir1/dir2/dir3/dir_or_file
读操作:对目录dir1、dir2、dir3、dir_or_file加读锁(即这些路径只能被并发读)。
写操作:对目录dir1、dir2、dir3加读锁,dir_or_file加写锁(dir_or_file不能读也不能写)。
Q1:死锁的处理,操作1:将/dir1/dir2移动到/dir3/dir4目录下(dir2不能读写且需要读写dir4),操作2:将dir3/dir4移动到/dir1/dir2目录下(dir4不能读写且需要写dir2)。当2个操作并发时,可能会死锁。

4.3 删除、移动和拷贝

删除:采用延迟删除的方式,删除时增加标识,后台线程定时扫描要删除的文件。步骤如下:

 1. 处理删除命令,标记Master中的Meta文件删除,通常在标记为删除3天后可正式删除。
 2. 后台线程定时扫描Master中要删除的文件,删除相关的Meta信息。
 3.  ChunkServer通过心跳上报chunk信息时发现包含的chunk不对应任何有效文件,Master通知ChunkServer删除该chunk。

移动:在Master中修改Meta信息即可完成。
拷贝:采用COW机制,即使用时拷贝,首先拷贝一份Meta信息,并增加最后一个chunk的引用计数(如果一个文件有N个chunk,则前N-1个chunk无需拷贝,共享即可)。通过取消租约的方式停止向第N个chunk写数据,当有写操作时,先拷贝一份第N个chunk,取消引用计数,然后向拷贝出来的chunk写数据。

4.4 写数据
  1. 概述,client写数据时,先向Master具体写的chunk信息(Master通过租约lease的方式指定一个Primary chunk,其余的为Seondary chunk)。后续client向chunk发数据并向Primary发送写请求。
  2. 流程图


    写数据流程图
  3. 流程解析
    step1、2:client发送请求,Master分配租约、返回chunk信息。
    step3:client将要写的数据发送个chunk。
    step4:client向Primary chunk发送写请求。
    step5:Primary确定写数据的offset和顺序(即如果有多条数据,多条数据间的顺序),通知Secondary开始写数据。
    step6:Secondary写数据成功,通知Primary。
    step7:Primary通知client写数据成功。
  4. lease租约的管理
    前提:当Chunk拥有租约时才会认为自己是Primary并处理写命令,通常租约为60S。
    case1:写操作时租约自动到期。通过心跳来续租约,避免租约自动到期。
    case2:Primary宕机。client重新向Master发送请求,Master重新分配租约。
    case3:Primary网络波动,但新的Primary已产生,存在2个Primary。增加version字段,多个Primary时,比较version,同时Master存储一个version字段,version大于等于Master中的version时才有效,每次分配lease时,version自增。
  5. 特殊Case分析
    case1:单client,数据不越界。无需特殊处理。
    case2:单client,数据超出chunk容量。写失败,将chunk的空白区填充数据。
    case3:单client,写失败,重试后成功。重试即可。
    case4:单client,写失败,重试后仍失败(如某个chunk所在物理机宕机)。
    case5:多client,数据不越界。无需特殊处理。
    case6:多client,总数据超出chunk容量。未超出的部分写入chunk,超出部分失败重试。
    case7:多client,总数据超出chunk容量,且在旧的chunk上写数据失败。
  6. 数据流的优化,从client将数据传给所有的chunk可以优化为client传给最近的chunk,由chunk链式传递给其它的剩下的chunk。
  7. 数据准确性的保证。在每个chunk末尾,记录当前chunk数据块的checksum。
4.5 读数据

根据offset定位到具体的chunk,读取数据,但是如上,存在空白区,读取时需特殊处理。

五、高可用的保证

5.1 chunk的复制

每个chunk都有多个副本,并可以配置副本的数量。
副本的分布:通常副本要在不同的机房,保证当整个机房出现问题时,数据不会丢失。
副本的拷贝:当副本配置数量增加或者部分副本永久失效时,需要拷贝副本(论文没有说明如何拷贝副本)。

5.2 chunk的过期检测

当Chunk服务器失效时,其中部分chunk数据更新不及时,因此上面的数据是无效的,在每个chunk中记录一个version(该version和lease的version相同),如果Master中其它同副本的chunk版本号更高,说明该chunk的数据未及时更新,需要删除该数据。

5.3 Master的复制

主从,RDB,AOF。。。

5.4 checksum保证数据完整

每个chunk块在末尾增加整个chunk的checksum,在读取时需根据记录的checksum校验该chunk块的数据的准确性。

你可能感兴趣的:(GFS--Google File System论文翻译和理解)