谷歌文件系统- GFS详解

?Google文件系统(简称GFS)是一个大规模可扩展的分布式文件系统,可以部署在廉价的商用服务器上,保证了系统的可靠性和可用性,大大降低了系统的成本。GFS的设计目标是高性能、高可靠性和高可用性。

?GFS将机器故障视为正常现象,可以很好地处理系统故障。GFS系统通常部署在数百甚至数千台廉价服务器上,相当一部分廉价服务器会部署GFS客户端来访问GFS服务,所以应用程序故障、操作系统bug、连接故障、网络故障,甚至机器电源故障都是经常发生的故障。GFS系统可以支持系统监控、故障检测、容错和自动恢复,提供非常高的可靠性。其次,GFS系统中的文件一般都是大文件,大多数场景下文件操作都是追加而不是覆盖。一旦文件被写入,大多数操作都是读取文件并按顺序读取。

?GFS提供了非标准(如POSIX)文件系统接口,支持创建、删除、打开、关闭、读写。此外,GFS支持快照和记录追加操作。Snapshot可以以非常低的成本创建文件或目录树的副本,record append可以支持多个客户端并发地向同一个文件追加数据,同时保证每个客户端追加操作的原子性。

?Master记录文件系统的元数据,包括命名空间、权限控制信息、文件到块的映射以及块的分布。Master还负责组块的租用管理、无用组块的垃圾收集、组块迁移等。Master定期与chunkserver通信,向chunkserver发送指令,并收集chunkserver的状态。GFS客户端通过GFS API与GFS系统通信(读取和写入数据)。客户端请求master获取元数据,真正的读写数据是直接和chunkserver交互。客户端和chunkserver都不会缓存文件数据。因为大多数应用程序基于API流读取大文件,并且系统中有太多的文件数据,所以客户端缓存文件数据是没有意义的。Chunkserver的Linux缓冲区缓存和频繁访问的数据被缓存,chunkserver也不缓存文件数据。

?单点master大大简化了系统设计,因为master知道所有元信息,所以可以执行更复杂的块位置分配和复制策略。但读写数据时必须减少master的参与,避免单点master被称为系统瓶颈。客户端不会通过master读写文件数据,但是会向master发送请求,查询chunk的位置分布,然后客户端会缓存chunk的分布信息,然后直接向chunkserver读写数据。一般的阅读过程如下:

1.客户端根据文件名、字节偏移量和块大小计算要读取的文件的块索引。

2.客户端通过文件名和块索引向主机查询块的分布情况。

3.主服务器回复块处理程序和副本分发。

4.客户端缓存块的元信息,关键字由文件名和块索引组成。

5.客户端从组块的分布信息中找到最近的组块服务器,并发送查询请求。查询请求包括块处理器和字节范围。对同一个块的后续查询不需要再次向主服务器查询元信息,因为客户端已经缓存了元信息。

?Chunk size是GFS系统的关键参数,通常设置为64MB,远大于文件系统的块大小。每个块的副本作为Linux文件存储在chunkserver所在的机器上。我们所做的是将块大小设置为64MB,主要考虑以下几点:

1,可以减少客户端访问主机查询元信息的次数,减轻主机的访问压力。因为组块大小设计比较大,所以顺序访问超大文件时,组块数量少,客户端缓存组块元信息,所以访问master的次数会减少。甚至客户端可以缓存所有文件的chunk的元信息,即使文件被随机读取,主端也不会成为系统性能的瓶颈。

2.可以减少网络开销,保持客户端和chunkserver之间的TCP连接,执行更多的chunk操作。

3.它可以减少需要记录在主机上的存储器中的元数据数据的量,并减少主机的存储器占用。

?大尺寸缺点是小文件包含很少的块,甚至只有一个。在这种情况下,当多个客户端查询高并发的小文件时,相应的组块就会成为热点。事实上,这种情况在GFS系统中很少发生,因为客户端的大部分操作都是顺序读取大文件。然而,考虑以下场景:我们将服务的二进制文件部署到GFS系统,然后数百个服务器同时查询二进制文件并启动服务。此时,二进制文件副本所在的chunkserver会立即成为查询瓶颈。当然,这种场景下的问题可以通过增加副本数量,分散服务器的查询时间来解决。

?Master主要存储三种类型的元数据:文件和块名称空间、从文件到块的映射信息以及块的副本分布。所有元数据都存储在主服务器的内存中。前两种元信息可以持久存储,操作日志存储在主机的本地磁盘上,备份日志存储在远程机器上。Master并不持久存储chunk的副本分布信息,而是通过与chunkserver交互获取chunkserver上的chunk信息。

4.1内存数据结构

?元信息在内存中,所有的主操作都非常快。此外,master还可以在后台高效、定时地扫描所有元数据,进行垃圾收集、副本修复、平衡等。元数据是记录在内存中的,所以GFS系统会更加关注chunk的数量和master的可用内存。但在实际场景中,这不是问题。每个64MB区块的元数据小于64个字节,大多数区块都是满容量存储的,只是文件最后一个区块的空间没有完全占用。因为文件命名空间是通过前缀压缩存储的,所以单个文件的元信息少于64个字节。如果需要扩展系统规模,可以简单的增加主控的内存。相对于系统的高可靠性、高性能和简单性,增加内存是成本最小的。

4.2组块分布

?我们不是持久存储chunk的副本分布信息,而是在主服务器启动时向chunkserver查询其chunk信息,然后通过heartbeat不断更新主服务器的副本分布信息,与chunkserver的数据保持一致。起初,GFS试图将chunk的分布信息永久存储在主服务器中,后来发现通过主服务器启动拉取chunk信息,然后通过heartbeat进行同步更简单。因为,chunkserver在频繁加入、退出、改名、重启的时候,维护master的Chunkmetadata的正确性会非常困难。从另一个角度来看,集群中只有chunkserver上报的块信息才是最真实的块分布,因为主节点不需要自己维护一个块分布状态,只需要服从chunkserver的状态报告即可。

4.3操作日志

?该日志记录GFS集群数据更改的历史。操作日志对于GFS来说非常重要,因为它不仅是元数据的持久记录,还记录了并发操作的时间顺序。因为操作日志非常重要,所以必须可靠地存储。在元数据的改变被持久化之前,客户端看不到数据的改变。当客户端修改数据时,需要将操作记录保存在多个远程机器上,只有将操作记录永久保存在本地和远程,客户端的数据更改才会成功。

?您可以通过回放操作日志来恢复文件系统。为了减少系统启动时的重播时间,有必要减少重播日志的数量。主服务器可以定期存储元数据的检查点。当主服务器重新启动时,它可以从检查点加载元数据,然后回放检查点之后的一些日志。

1.客户端向主服务器查询一个chunk的主服务器所在的chunkserver和其他副本的分布情况。如果没有主花,主花将选择一朵作为该花块的主花。

2.主回复客户端主副本和其他副本的分发信息。客户端缓存返回的元数据。

3.客户端发送数据的所有副本。客户端可以以任何顺序执行。每个chunkserser在内存的LRUbuffer中记录数据。

4.在所有拷贝成功返回接收到的数据后,客户端将向主节点发送写入请求。Primary将为每个数据更改请求附加一个序列号,数据更改按序列号的顺序执行。

5.主服务器将数据更改同步到其他副本服务器,副本服务器也根据序列号执行数据更改。

6.主服务器收到其他副本回复的数据操作完成。

7.primary返回客户端结果。在此期间发生的所有错误都将报告给客户。

?GFS集群通常有数百个chunkserver,分布在多个机架上。Chunkserver还将接收来自该机架或其他机架中的数百个客户端的查询请求。不同机架中的服务器流量可以通过一个或多个交换机转发。chunk的副本分布选择策略的主要目的是尽可能提高数据的可靠性和可用性,同时尽可能充分利用网络带宽。因此,仅仅跨机器部署副本是不够的。GFS跨机架部署副本,这可确保当机架损坏或脱机时,至少有一份数据块副本可用。

?将在以下情况下创建区块的副本:创建区块、复制修复、重新平衡。当master创建块时,它选择存储块副本的chunkserver。主要考虑以下几点:

1.新副本所在的chunkserver的磁盘利用率低于系统平均水平。

2.限制最近一段时间内每个chunkserver创建的块的数量。

3.每个区块的所有副本不能在一个机架中。

?Chunk的副本数量少于特定数量。是的,师父会复印一份。当chunkserver关闭,或者chunkserver报告其副本损坏,或者chunkserver所在机器的磁盘损坏等等时,可能会发生这种情况。每个块复制任务都有一个优先级,在子主机中按从高到低的顺序排队等待执行。Master还会定期扫描当前副本的分布情况,一旦发现磁盘使用或机器负载不平衡,就会启动负载平衡操作。无论是组块创建、组块复制还是负载均衡,选择组块副本位置的策略都是一样的,需要限制副本修复和均衡的速度,否则会影响系统的正常读写服务。

?谷歌的成功表明,单一的主设计师是可行的。这不仅简化了系统,而且可以很好地实现一致性。考虑到性能,GFS提出了“至少原子地添加记录”的一致性模型。每个chunk的修改通过租借授权给chunkserver,这样减轻了master的负荷,通过管道复制多个副本来减少延迟。Master维护大量元数据,需要设计高效的数据结构,并保证占用内存少,支持快照操作。b树支持COW可以满足需求,但是实现真的挺复杂的。