Google File System笔记

来源:互联网 发布:bp神经网络算法 剃度 编辑:程序博客网 时间:2024/06/08 04:11

Google的文件系统

The Google File System by S. Ghemawat, H. Gobioff and S.T.Leung

需求:

1.      文件系统是由成百上千的机器组成。要考虑到机器出现故障的情况。

2.      Google需要存储大量数据,文件的大小以>100MB为计。

3.      读取:大量数据流读取,少量随机读取。

4.      写入:在文件末尾追加。

5.      并行追加有合理的定义。

6.      高带宽比低延迟更重要。

接口:

1.      Create, delete, open, close, read, write

2.      Snapshot: 以较低代价对文件或目录树进行复制。

3.      Record append: 并发的追加中,每次追加均为原子操作。

架构:

1.      一个单独的master和多重chunkservers。均采用linux操作系统。Client可以在chunkservers上运行。

2.      文件被分为固定大小的chunk,每个chunk有64位的handle。Chunk本身是Linux文件。(what’s the underlying filesystem? Ext4? Reiserfs? Or ?)

3.      每个chunk都有在不同chunkserver上的多个复制(保证数据可靠性)。一般3个拷贝。

4.      Master保存文件系统的所有metadata,包括namespace,access control information,文件到chunk的mapping和chunk的当前位置。也处理对orphanchunk的GC,chunkserver之间chunk的移植。

5.      Master通过一个HeartBeat信号定期和chunkserver交流。

6.      GFS以库链接入程序,不用POSIX接口。

7.      无cache,使用linux本身的缓存。

单个master:

Client访问master关于chunkserver的信息,然后直接和chunkserver沟通。不通过master进行io。Chunkserver的信息在client上有cache。

Chunk的尺寸:

定义64MB为chunk大小。(what happens to local filesystem?)

Pros:这样可以减少master的负担,降低chunkserver和client之间的网络问题。减少metadata的大小。

Cons:如果一个小文件只有一个或少数几个chunk,但是多个client访问之,则影响性能。但实际上这种问题可以忽略不计,可以考虑client之间交换数据(similarto bittorrent)。

Metadata:

内容:

1.      文件和chunk的namespace

2.      文件到chunk的映射

3.      每个chunk的复制的位置

前两部分数据保存在内存里。(多次使用)

同时用一个log更新master的数据。

Master不保存chunk的位置信息,而是在master启动或者有新的chunkserver接入时才更新。(因为chunk保存进去就不会再被更改)chunk的信息可以通过backgroundscan完成。

内存中的数据结构:

Background scan用来进行chunk的垃圾回收(为什么要回收?不删除只增加),当chunkserver故障时对数据(已经在其他chunkserver有备份)进行复制,移植chunk平衡负载。

内存数据并不很大。每个chunk只有64bit的记号,而且大部分chunk是满的,只有在最后的chunk才会被写入。Chunk和文件名的对应也不大,因为文件名可以经过压缩(控制可用的文件名,然后用位进行一一对应?)。

Chunk的位置:

Master不持久记录chunk的位置。只在开机的时候进行扫描,或者通过heartbeat进行更新。这样可以解决同步问题。而且chunkserver的更换可能造成数据的inconsistency。

操作log:

Log记录关键metadata的更改:对并发起到定义操作顺序的作用。

Log必须在实际的metadata更改之后才进行更新,保持consistency。在一个文件操作结束且log更新之后再通知client。

几个log操作结束之后才写入log,降低io负担。

通过log replay来恢复文件系统状态。为了减少replay数量,在log达到一定数值时使用checkpoint。在生成checkpoint时,用另外的线程来保存新的log。

Consistency Model:

为了保证文件系统的可靠性,定义:

Consistency:所有client读取的文件内容都是一致的,无论chunk的复制在哪一台chunkserver上。

Defined:若写入文件,文件consistency并且所有的client都能看到更改的内容。

 

写入

追加记录

顺序操作,成功

Defined

Defined,但是写入的内容和读取的内容可能不同(并发操作)。

并发操作,成功

Consistent,但是不defined

失败

Inconsistent

并发写入时,可能产生的结果是因为写入顺序不同,写入的值defined,但是每个进程之后读取的可能不是写入的资料。

失败的操作将可能导致不同的client读取到不同的数据。

写入不是atomic的,但是追加记录是atomic的。

顺序操作必然是defined,因为gfs保证对所有的相关chunk进行相同的操作,并且使用chunk的版本号来确认因为某种原因更新失败(e.g.操作时chunkserver不在线)的chunk不可靠。这些outdated的chunk将被GC掉。

对于失效的chunk,master定时handshake,通过checksum来确认。如果chunk数据损失,将通过其他拷贝来进行恢复。只有所有拷贝都失效才会导致数据丢失。

对应用程序的要求:

应用程序应当:依靠追加记录,而不是覆盖记录;使用checkpoint来保存写入成功的进展程度(失败时进行incrementwriting);写入识别写入者身份的record。

当只有一个client进行一个文件的写入时,通过checkpoint来存进度。

许多client并发写入时,可能产生“生产者-消费者”队列。每个client应当在写入时添加checksum来确保写入成功,

系统操作:

操作时应当尽量减少和master的沟通。

Lease和变更顺序:

每次对数据的修改都将影响到所有保存这个数据的chunk。Lease就是用来管理统一的更改的方式。Master将给一个chunk的一个拷贝一个lease,这个chunk记作primary。Primary的拷贝选定对chunk的操作顺序,然后所有其他的拷贝都按照这个顺序进行修改。

Lease的目的是减轻master的负担。一个lease有60秒的timeout,只要还在进行操作,primary就可以申请延长时间。Master可以暂停lease(例如master给一个文件改名)。如果一个primary丢失,可以使用另外一个primary。

写操作顺序:

1.      Client询问master那一个chunkserver有当前chunk的lease。如果没有,master将给一个chunkserver以lease。

2.      Master返回primary和其他的拷贝。Client缓冲数据。

3.      Client将数据发送给所有有拷贝的chunkserver。Chunkserver缓存之。

4.      数据发送确认成功后client指示chunkserver写入数据。Primary将确认数据写入顺序(可能来自多个client的数据),然后实施写入。

5.      Primary将写入顺序分配给其他chunkserver,其他chunkserver按照相同顺序写入。

6.      写入完成后报告primary。

7.      Primary报告client。失败时可能重复3-7操作。

数据流:

为了减轻网络负担,数据不是通过一台机器同时传给多台其他chunkserver的,而是一台chunkserver传给另一台chunkserver,依次传递的。传递的原则是传给未接受数据而在网络拓扑结构上最近的机器(这个可以通过IP地址计算)。每台chunkserver并不是等待数据接受完毕再开始发送,而是在接受的同时进行发送。

数据追加:

GFS提供原子操作式的数据追加。操作时,被追加的数据将连续写入,保持不间断(上锁?),返回写入的offset。

实现:client将数据(数据量限定在一个chunk最大尺寸的四分之一)发送给所有持有相应chunk的机器,然后向primary发送信息。Primary检查写入数据是否超过一个chunk的尺寸,并写入数据(跨chunk写入如何进行?createa new chunk or separate the data to two chunks?)。

如果一台机器写入失败,系统将重试,这样不同拷贝内容可能不同。GFS不保证数据一致性。

系统快照:

系统快照复制一个文件或一个目录结构,需要尽量少的中断文件写入操作。使用COW。开始生成快照时,首先向master发送申请,然后master收回所有对chunks的lease(封锁数据)。之后对操作进行log。新的snapshot将首先指向原来的数据。之后如果有写入操作的话,master将发现chunk的引用计数大于一,于是暂停写入,让每个有此chunk的chunkserver对此chunk进行复制(复制不需要网络连接)。之后对新的chunk进行操作。

MASTER的操作:

名字空间管理,上锁:

Master的操作可能消耗很长时间,因此必须允许多个操作并发进行。

GFS没有传统目录形式的文件结构,也没有引用。GFS通过一个lookuptable来对应路径和metadata的联系。这个table可以保存在内存中。每个namespacetree的node有一个读写锁。

每个master操作都首先要获得相应的lock。例如对/d1/d2/../dn/leaf操作,则首先取/d1,/d1/d2, etc. 的读锁,然后再取/d1/d2…/dn/leaf的读写锁。

这样的操作保证对目录中的文件的并行操作。读锁保证目录在操作时不被snapshot,删除,改名。写锁防止相同文件名的文件被再次创建。

因为node数量大,所以只有在需要锁的时候才创建锁,在不需要锁的时候就删除之。为了防止死锁,首先在namespacetree的level取得锁,然后再按顺序取得相同level的锁。

拷贝管理:

 拷贝的目的:保证数据的可靠性以及可访问性。

进行广泛的拷贝,防止故障带来的数据丢失。这样也可以减轻读取的负担,但是会增加写入负担。

创建拷贝,重新拷贝,重新调整拷贝的平衡性:

Master在创建chunk时决定chunk的位置。考虑因素:1.放在磁盘空间使用率低于平均水平的机器上2.限制在每个chunkserver上一定时间内的creation,以平衡写操作3.将chunk分布到不同机组上。

如果拷贝个数低于某个值,例如chunkserver故障,chunkcorruption,或者仅仅是需要更多的拷贝,则进行重新复制。其优先度由:1.距离目标拷贝个数有多远2.先拷贝现在活跃的chunk,而较少考虑标记为删除的chunk3. 若对chunk的IO有较大需求则优先考虑。

为控制对整个网络的影响,限制clone需要的网络带宽。

Master在一段时间后会重新balancechunk的存放。

GC:

原理:删除文件操作并不物理释放文件占用空间,而只是更改文件名,标记删除时间。一定时间后才真正进行释放空间的操作。这确保文件可以被恢复。

同时对orphan的chunk进行扫描(类似java的GC)。方法是在一次heartbeat中每个chunkserver汇报其拥有的chunk,而master与其持有的metadata比较,若metadata中没有这个chunk的信息,则释放这个chunk。

可以不删除chunk,只是标记为availabe,这样减轻创建文件的负担。

损坏拷贝的检查:

Master管理chunk的版本号。每次释放一个lease时,增加chunk的版本号。在chunkserver重启的时候,版本号较低的被认为是损坏的拷贝,将不被考虑。在GC的时候损坏的拷贝被移除。在clone和给出lease的时候也会检查版本号。

错误控制和检测:

Master也有副本,在一个master关闭时可以重新在机器上迅速开启新的master。

每个chunkserver都检查数据完整性,以64kb为界,每64k数据有32bit的checksum。读取的时候,chunkserver检测数据的checksum。读取时检测checksum。如果checksum出错,则master将不再信任这个chunk,并且准备这个chunk的新的复制。

在追加数据时,checksum是增量计算的。这样即便之前的数据是corrupted的,计算出的checksum也将和数据不同。覆盖数据时则需要找到相对应的block,然后计算checksum。

在计算机空闲时期,chunkserver将通过checksum检查数据的完整性。

 

原创粉丝点击