GFS阅读-下

这篇文章是阅读GFS记录的点滴,参考了Charles的博客,上面有很多关于分布式以及其他一些学习内容

Posted on May 30, 2017 in DistributedSystem, ReadPaper



#3 SYSTEM INTERACTIONS


GFS的设计是让master减少对数据请求的参与度,下面将探讨**master**、**chunkserver**与**client**是如何进行交互操作的来实现修改数据、原子性的record append以及snapshot。


##3.1 Leases and Mutation Order

 GFS master对后续的数据流程是不做控制的,所以,需要一个机制来保证,所有副本是按照同样的操作顺序写入对应的数据的。GFS采用lease方式来解决这个问题,GFS对一个chunk会选择一个GFS chunkserver,发放lease,称作primary,由primary chunkserver来控制写入的顺序。


- 注意:lease是gfs master把控制写入顺序的权限下放给chunkserver的机制,以减少gfs master在读写流程中的参与度,防止其成为系统瓶颈。


Lease的过期时间默认是60s,可以通过心跳信息来续时间,如果一个primary chunkserver是正常状态的话,这个时间一般是无限续下去的。当primary chunkserver和GFS master心跳断了后,GFS master也可以方便的把其他chunk副本所在的chunkserver设置成primary。

image.png


1. GFS client向GFS master请求拥有具有当前chunk的lease的chunkserver信息,以及chunk的其他副本所在的chunkserver的信息,如果当前chunk没有lease,GFS master会分配一个。

2. GFS master把primary chunkserver以及其他副本的chunkserver信息返回给client。client会缓存这些信息,只有当primary chunkserver连不上或者lease发生改变后,才需要再向GFS master获取对应的信息。

3. client把数据(将要写入chunk的新数据)推送给所有包含此chunk的chunkserver,chunkserver收到后会先把数据放到内部的LRU buffer中,当数据被使用或者过期了,才删除掉。注意,这里没有将具体怎么来发送数据,会在下面的Data Flow讲。

4. 当所有包含chunk副本的chunkserver都收到了数据,client会给primary发送一个写请求,包含之前写的数据的信息,primary会分配对应的序号给此次的写请求,这样可以保证从多个客户端的并发写请求会得到唯一的操作顺序,保证多个副本的写入数据的顺序是一致的。

5. primary转发写请求给所有其他的副本所在的chunkserver(Secondary replica),操作顺序由primary指定。

6. Secondary replica写成功后会返回给primary replica。

7. Primary replica返回给client。任何副本发生任何错误都会返回给client。


如果数据库太大或者是跨数据块的操作,一般会将这个请求拆分。这里,写数据如果发生错误可能会产生不一致的情况,会在consistency model中讨论。



##3.2 Data Flow

3.1中第三步的Data Flow采用的是**pipe line**方式,目标是为了充分利用每台机器的网络带宽。假设一台机器总共有三个副本S1-S3。整个的Data Flow为:

1.client选择离它最近的chunkserver S1,开始推送数据

2.当chunkserver S1收到数据后,它会立马转发到离它最近的chunkserver S2

3.chunkserver S2收到数据后,会立马转发给离它最近的chunkserver S3

4.不断重复上述流程,直到所有的chunkserver都收到client的所有数据。

以上述方式来传送B字节数据到R个副本,并假设网络吞吐量为T,机器之间的时延为L,那么,整个数据的传输时间为B/T+RL。

##3.3 Atomic Record Appends

Append操作流程和写差不多,主要区别在以下


1.client把数据推送到所有副本的最后一个chunk,然后发送写请求到primary

2.primary首先检查最后一个chunk的剩余空间是否可以满足当前写请求,如果可以,那么执行写流程,否则,它会把当前的chunk的剩余空间padding起来,然后告诉其他的副本也这么干,最后告诉client这个chunk满了,写入下个chunk。

这里需要讨论的是,如果append操作在部分副本失败的情况下,会发生什么?


例如,写操作要追加到S1-S3,但是,仅仅是S1,S2成功了,S3失败了,GFS client会重试操作,假如第二次成功了,那么S1,S2写了两次,S3写了一次,目前的理解是GFS会先把失败的记录进行padding对齐到primary的记录,然后再继续append。

##3.4 Snapshot

Snapshot的整个流程如下:

1.client向GFS master发送Snapshot请求。

2.GFS master收到请求后,会回收所有这次Snapshot涉及到的chunk的lease。

3.当所有回收的lease到期后,GFS master写入一条日志,记录这个信息。然后,GFS会在内存中**复制**一份snapshot**涉及到的metadata**。


当snapshot操作完成后,client**写**snapshot中涉及到的chunk C的流程如下:

1.client向GFS master请求primary chunkserver和其他chunkserver

2.GFS master发现chunk C的引用计数超过1,即snapshot和本身。它会向所有有chunk C副本的chunkserver发送创建一个chunk C的拷贝请求,记作是chunk C’,这样,把最新数据写入到chunk C’即可。本质上是**copy on write**。

#4 MASTER OPERATION

GFS中master的操作包括

- namespace(directories) operation

- manage chunk replicas

- make placement decision

- coordinate various system-wide activities

- balance load

- reclaim unused storage

##4.1 Namespace(directories) management and locking

每个master操作都需要获得一系列的锁。如果一个操作涉及到/d1/d2/…/dn/leaf,那么**需要获得**/d1、/d1/d2、/d1/d2/…/dn的**读锁**,然后,**根据操作类型**,**获得**/d1/d2/…/dn/leaf的**读锁**或者**写锁**,其中leaf可能是文件或者路径。


一个例子,当/home/user被**快照**到/save/user的时候,/home/user/foo的**创建**是被禁止的。

对于**快照操作**,需要获得/home和/save的**读锁**,/home/user和/save/user的**写锁**。对于**创建操作**,会获得/home,/home/user的**读锁**,然后/home/user/foo的**写锁**。其中,/home/user的锁产生**冲突**,/home/user/foo创建会被禁止。


这种加锁机制的**好处**是对于同一个目录下,可以并行的操作文件,例如,同一个目录下并行的创建文件。

##4.2 Replica Placement

GFS的Replica Placement的两个目标:最大化数据可靠性(reliability)和可用性(availability),最大化网络带宽的使用率。因此,把每个chunk的副本分散在不同的机架上,这样一方面,可以抵御机架级的故障,另一方面,可以把读写数据的带宽分配在机架级,重复利用多个机架的带宽。



##4.3 Creation, Re-replication, Rebalancing

数据的复制有三种原因:数据创造、数据再复制与数据再均衡控制。

- Chunk Creation

GFS在创建chunk的时候,选择chunkserver时考虑的因素包括:

1.磁盘空间使用率低于平均值的chunkserver

2.限制每台chunkserver的最近的创建chunk的次数,因为创建chunk往往意味着后续需要写大量数据,所以,应该把写流量尽量均摊到每台chunkserver上

3.chunk的副本放在处于不同机架的chunkserver上


- Chunk Re-replication

当一个chunk的副本数量少于预设定的数量时,需要做复制的操作,例如,chunkserver宕机,副本数据出错,磁盘损坏,或者设定的副本数量增加。

chunk的复制的优先级是按照下面的因素来确定的:

1.丢失两个副本的chunk比丢失一个副本的chunk的复制认为优先级高

2.文件正在使用比文件已被删除的chunk的优先级高

3.阻塞了client进程的chunk的优先级高(这个靠什么方法得到?)

chunk复制的时候,选择新chunkserver要考虑的点:

1.磁盘使用率

2.单个chunkserver的复制个数限制

3.多个副本需要在多个机架

4.集群的复制个数限制

5.限制每个chunkserver的复制网络带宽,通过限制读流量的速率来限制


-  Rebalancing

周期性地检查副本分布情况,然后**调整**到更好的**磁盘使用情况**和**负载均衡**。GFS master对于新加入的chunkserver,逐渐地迁移副本到上面,防止新chunkserver带宽打满。


##4.4 Garbage Collection

在GFS删除一个文件后,并不会马上就对文件物理删除,而是在后面的定期清理的过程中才真正的删除。

具体地,对于一个删除操作,GFS仅仅是**写一条日志log记录**,然后把文件**命名**成一个对外部不可见的名称,这个名称会包含删除的时间戳。GFS master会定期的扫描,当这些文件存在超过3天后,这些文件会**从namespace目录中删掉**,并且内存的中**metadata会被删除**。

在对chunk namespace(目录)的定期扫描时,会扫描到这些文件已经被删除的chunk,然后会把metadata从磁盘中删除。

在与chunkserver的**heartbeat心跳**的交互过程中,GFS master会把不在metadata中的chunk告诉chunkserver,然后chunkserver就可以删除这些chunk了。

采用这种方式删除的好处:

1.利用心跳方式交互,在一次删除失败后,还可以通过下次心跳继续重试操作

2.删除操作和其他的全局扫描metadata的操作可以放到一起做

坏处:

1.有可能有的应用需要频繁的创建和删除文件,这种延期删除方式会导致磁盘使用率偏高,GFS提供的解决方案是,对一个文件调用删除操作两次,GFS会马上做物理删除操作,释放空间。



##4.5 Stable Replica Detection

当一台chunkserver挂掉的时候,有新的写入操作到chunk副本,会导致chunkserve的数据不是最新的。

当master分配lease到一个chunk时,它会**更新chunk version number**,然后其他的副本都会更新该值。这个操作是在返回给客户端之前完成的,如果有一个chunkserver当前是宕机的,那么它的version number就不会增加。当chunkserver重启后,会汇报它的chunk以及version number,对于version number落后的chunk,master就认为这个chunk的数据是落后的。

GFS master会**把落后的chunk当垃圾来清理掉**,并且不会把落后的chunkserver的位置信息传给client。

- 备注:GFS master把落后的chunk当作垃圾清理,那么,是否是走re-replication的逻辑来生成新的副本呢?没有,是走立即复制的逻辑。



#5 FAULT TOLERANCE AND DIAGNOSIS

部分失效是分布式系统的一大挑战,需要使系统对失效问题作出快速的诊断与恢复。


##5.1 High Availability

两种方式有效实现高可用——快速恢复与备份!

### 5.1.1 Fast Recovery

master和chunkserver都被设计成都能在秒级别重启

### 5.1.2 Chunk Replication

每个chunk在**多个机架**上有副本,副本数量由用户来指定。当chunkserver不可用时,GFS master会自动的复制副本 Re-replication,保证副本数量和用户指定的一致。

### 5.1.3 Master Replication

master的operation log和checkpoint都会复制到多台机器上,要保证这些机器的写都成功了,才认为是成功。只有一台master在来做garbage collection等后台操作。当master挂掉后,它能在很多时间内重启;当master所在的机器挂掉后,监控会在其他具有operation log的机器上重启启动master。

新启动的master只提供读服务,因为可能在挂掉的一瞬间,有些日志记录到primary master上,而没有记录到secondary master(shadow master)上,若执行写操作会导致不稳定的结果。



##5.2 Data Integrity

每个chunkserver都会通过checksum来验证数据是否损坏的。

每个chunk被分成多个64KB的block(若64MB就有1024个block),每个block有32位(4字节)的checksum,checksum在内存中和磁盘的log中都有记录。

对于读请求,chunkserver会检查读操作所涉及block的所有checksum值是否正确,如果有一个block的checksum不对,那么会报错给client和master。client这时会从其他副本读数据,而master会clone一个新副本,当新副本clone好后,master会删除掉这个checksum出错的副本。



##5.3 Diagnostic Tools

主要是通过log,包括重要事件的log(chunkserver上下线),RPC请求,RPC响应等。