GFS, Big Table, Map Reduce称为Google的三驾马车,是许多基础服务的基石 GFS于2003年提出,是一个分布式的文件系统,与此前的很多分布式系统的前提假设存在很大的不同,适用于以下场景 1)认为组件失效是一种常态,提供了容错机制,自动负载均衡,使得分布式文件系统可以在廉价机器上运行 2)面向大文件存储,系统主要的工作负载是大规模的流式读取,写操作主要是追加方式写,很少有随机写 3)一次写入,多次读取,例如互联网上的网页存储
一个GFS集群由一台master服务器(有备份),多台chunk服务器组成,客户端,架构上比较简单。
Chunkserver:数据存储节点,文件被分割为固定大小的Chunk,每个Chunk被唯一标识,默认情况下,Chunk存储为3个副本
Chunk:每个文件至少存储为一个chunk,每个chunk以普通linux文件存储,chuck尺寸大小选择是一个关键的设计参数,默认64MB,每个chunk有全局64位唯一标识符
Chunk尺寸较大优缺点?
较大:减小master上元数据大小,放在内存,减少client与master交互
缺点:小文件会存储为一个Chunk,多个Client同时对单个小文件多次操作时,存放这个Chunk的ChunkServer会成为热点
GFS master:管理所有元数据信息;租约管理;集群Chunk迁移;无用Chunk回收;
元信息(metadata)主要有三类:命名空间、文件和Chunk的映射关系(一个文件包含哪些Chunk)、每个Chunk副本的位置信息。元信息存储在内存中,加快处理速度。
前两类元信息会以操作日志文件存储在本地磁盘上,并复制到远程Master备机上,容灾需要。Chunk副本的位置信息为Master通过心跳向各个ChunkServer轮询获得,无需持久化,避免了ChunkServer变更时的Master和ChunkServer的数据同步问题。
GFS client:与 Master节点的通信只获取元数据,所有的数据操作都直接和 Chunk 服务器进行交互,GFS提供了一套类似传统文件系统的 API 接口
读流程:客户端向master请求<file_name, chunk index>,master返回chunk的位置信息,客户端再向对应的chunkserver请求
写流程:写通常又被细分成write和append,write是对已有数据的更新(指定偏移量offset),而append则是在文件的末尾增加新的数据。
GFS 供了一种原子的append操作,即Client只需指定要写入数据(而不用指定偏移值),GFS就保证至少有一次原子的写入操作执行成功,并返回追加成功的数据的起始位置的偏移值给Client。记录追加的引入是为了在分布式应用中,减少很多Client并行对同份数据写入的同步机制开销,例如使用一个分布式的锁管理器。
写操作会在所有副本上执行。
Master 节点选择某个副本为主 Chunk,并给其建立租约,租约默认60s,然后主Chunk协调客户端的写入,保证多副本之间维持一个全局统一的更新顺序。
使用租约机制来保障数据多个副本变更顺序的一致性,租约序列由主Chunk产生,chunk 租约机制的设计主要是为了减轻 Master 的负担,由主副本所在的 chunkserver 来承担流水线顺序的安排。
租约本质上是一种有时间限制的锁:租约的持有者(chunk的某个副本)需要定期向Master申请续约。如果超过租约的期限,那么该租约会被强制收回并重新分配给其他副本。
数据写入流程:
这里需要说明的是客户端的数据写入被拆成了数据推送和sync两个子命令,这是因为:
sync是将上面推送的数据落盘,需要保证多副本上数据写入顺序的一致性,该指令必须由主副本确定数据更新顺序然后将该顺序通知给其他从副本。
主副本等待sync过程中写某个从副本失败,如何处理?
客户端收到请求失败消息后,然后对步骤3到7全部重试
GFS定义了下列几种一致性:总体而言,是弱一致性
defined:状态已定义,从客户端角度来看,客户端完全了解已写入集群的数据。即当一个客户端写文件,之后读能否读出之前写的文件,也就是说和自己的写的是否一致。
consistent:客户端来看chunk多副本的数据完全一致,但不一定defined
unconsistent:多副本数据不一致
undefined:数据未定义
无论是串行write还是并行write,一旦失败,多个chunk副本上的数据可能都不一致了,其次,客户端从不同的副本上读出的数据也不一样(可能某些副本成功而某些副本失败),因此,必然也是undefined,也是inconsistent
对于append操作,客户端无需指定offset,由chunk主副本根据当前文件大小决定写入offset,在写入成功后将该offset返回给客户端,因此,客户端能够根据offset确切知道写入结果,无论是串行写入还是并发写入,其行为是defined。对于如果append第一次失败,导致多副本在10-60的数据可能不一致,但接下来重试成功,从60至110之间的数据一致,因此,其状态是interspersed with inconsistent(部分不一致)。
注:追加操作和写文件不一样,追加操作不是幂等的,当一次追加操作没有成功,客户端重试时,不同副本可能被追加了不同次数,也可能填充数据。
1)命名空间管理
命名空间的修改通过锁保证为原子性的。
在逻辑上,GFS 的名称空间就是一个全路径和元数据映射关系的查找表。利用前缀压缩,这个表可以高效的存储在内存中。在存储名称空间的树型结构上,每个节点(绝对路径的文件名或绝对路径的目录名)都有一个关联的读写锁。采用这种锁方案的优点是支持对同一目录的并行操作,比如,每一个文件操作需要获取父目录读锁和目标文件写锁。目录名的读取锁防止目录被删除、 改名以及被快照。
如何避免死锁?
锁的获取依据全局一致的顺序,先按名字空间层次排序,同一层次按字典序排序
2)副本位置分布
GFS中chunk以多副本存储,以提高数据可靠性。一个好的副本位置定义算法满足下面特性:
3)Chunk的创建、负载均衡
当 Master 节点创建一个 Chunk 时,它会选择在哪里放置初始的空的副本,需要考虑以下几个因素:
4)垃圾回收
所有 Master 节点不能识别的副本都是“垃圾”。我们很容易能得到 Chunk 的所有引用: 它们都只存储在 Master 服务器上的文件到chunk的映射表中。 我们也可以得到所有 Chunk 的副本:它们都以 Linux 文件的形式存储在 Chunk 服务器的指定目录下。
GFS 在文件删除后不会立刻回收可用的物理空间,空间回收采用惰性的策略,周期性的常规垃圾扫描才回收物理空间,并在 Master 节点相对空闲的时候完成。
具体流程:Client提交文件删除操作,Master将删除操作记录到日志,并将对应文件名改为包含删除时间戳的隐藏文件名(改名字,并没有回收物理空间。Master周期性对名字空间做常规垃圾扫描,会在名字空间中删除3天前(时间可配置)的隐藏文件及元数据。ChunkServer在与Master的心跳信息中,得知哪些Chunk的元数据不存在了,便可实际回收其物理空间。直到文件被真正删除,它们仍旧可以用新的特殊的名字读取,也可以通过把隐藏文件改名为正常显示的文件名的方式“反删除”。当隐藏文件被从名称空间中删除,Master 服务器内存中保存的这个文件的相关元数据才会被删除,这也有效的切断了文件和它包含的所有 Chunk 的连接。
优点:设计简单,批量执行,防误删
缺点:存储的开销,阻碍用户调优存储空间使用,特别是当存储空间比较紧缺的时候。我们允许用户为命名空间的不同部分设定不同的复制和回收策略。例如,用户可以指定某些目录树下面的文件不做复制,删除的文件被即时的移除。
具体流程是:
Colossus
Google内部至少运行着200多个GFS集群,最大的集群有几千台服务器,数据量是PB级别的,并且服务于多个Google服务,包括Google搜索和Google Earth等。GFS对于大文件很友好,吞吐量很大,但是延迟较高,所以并不很适合新的一些Google产品,比YouTube、Gmail和非常强调实时性的Caffeine搜索引擎等,Google在2009年已经在开发下一代GFS,代号为“Colossus”。
几个改进如下:
Hadoop的分布式文件存储系统,完整实现了GFS论文中的概念模型,在某些方面做了简化处理:
原文:https://www.cnblogs.com/JBLi/p/10656556.html