了解GFS

参考:

  https://wenku.baidu.com/view/4392293517791711cc7931b765ce0508763275f2.html  论文翻译

  https://zhuanlan.zhihu.com/p/465532138                                                                       知乎友人解读

  https://mit-public-courses-cn-translatio.gitbook.io/mit6-824/lecture-03-gfs/3.4               mit 6.824 翻译

 

 


 

GFS设计目标:

  ①Google的目标是构建一个大型的,快速的文件系统。并且这个文件系统是全局有效的,不是为了特定系统裁剪的存储系统,类似与我们操作系统内的文件系统。

  ②为了获得大容量和高速的特性,每个包含了数据的文件会被GFS自动的分割并存放在多个服务器之上,这样读写操作自然就会变得很快。因为可以从多个服务器上同时读取同一个文件,

  进而获得更高的聚合吞吐量。将文件分割存储还可以在存储系统中保存比单个磁盘还要大的文件。

  ③希望有自动的故障修复。我们不希望每次服务器出了故障,派人到机房去修复服务器或者迁移数据。我们希望系统能自动修复自己。

  ④GFS在各个方面对大型的顺序文件读写做了定制。

  ⑤GFS并没有花费过多的精力来降低延迟,它的关注点在于巨大的吞吐量上,所以单次操作都涉及到MB级别的数据。


 GFS架构:

GFS集群由单个master和很多chunkserver(块服务器)组成。

GFS集群会有很多client访问,每一个节点都是普通linux计算机。

在GFS下,每一个文件都拆成固定大小的chunk,每个块都会由master根据块创建时间产生全局唯一不会改变的chunk handle标识,chunkservers在本地磁盘用linux文件保存这些块,根据chunk handle 和字节去捡,通过linux文件系统读写数据,

每一个块缺省状态会在3个不同chunkserver上保存。

master管理所有元数据。元数据就是数据的信息,保存着各种关于chunk位置或其他方面的信息,chunk server没有cache机制。

通过巧妙的设计减少单个master的读写,避免成为性能瓶颈。


 

 


 

Google设计的几个原则:简单原则、根据硬件特性做设计取舍、根据实际应用做设计取舍。

第一个,简单设计原则:

首要的简单是文件存储就是普通的Linux文件,充分利用了Linux特性。其次简单是单一的Master节点策略,这个就大大简化了设计,单Master让整个GFS的架构变得非常简单,避免了复杂的一致性问题。当然这也带来了很多限制,比如:一旦Master出现故障,整个集群就无法写入数据,而恢复Master就需要人工介入,从这一点来看,GFS Master节点并不是一个高可用的系统。那么怎么提高可用性呢?工程实现上有很多手段,GFS采用了Checkpoint、操作日志,引入影子节点Shadow Master等一系列手段,这再次印证了计算机技术实现上“扬长避短”的思想,发挥其长处,针对短处,采取一系列手段去优化弥补。

第二个,根据硬件特性做设计取舍:

首先,在GFS论文发表的年代,大家还在使用机械硬盘,对机械硬盘,我们都知道其随机读写的性能很差,所以GFS的设计中主要是顺序读写操作,以Append追加的方式写入数据,以流式访问读取数据。

其次,当时的数据中心,服务器的网卡带宽普遍是百兆网卡,网络带宽往往是系统的性能瓶颈,因此,GFS设计使用流水线式的数据传输机制。

第三,在文件复制操作时,GFS专门设计了一个Snapshot,其目的也是为了避免复制时数据在网络上传输。这些设计都是避免有限的网络带宽成为性能瓶颈。

第三个,根据实际应用做设计取舍:

GFS是为了在廉价硬件上做大规模数据处理而设计的,所以GFS的一致性相当宽松,GFS对随机写入的一致性没有任何保障,对于Append追加操作,GFS也只是做了“At Least Once”至少一次的保障。这个任务被交给了客户端,通过在客户端中实现校验、去重这样的处理机制,这样GFS在大规模数据处理上也可以很好适用。


 

 chunk 文件块大小选择

优点:

选择大chunk 可以减少客户端和master交互。

可以通过维持一个到chunkserver的TCP长链接减少网络管理量。

减少了元数据在master的大小

缺点:如果一个文件本来就很小,他就有很少的chunk,那保存这些文件的 chunkserver就会有大量客户端访问时成为焦点。

解决焦点问题:调整备份参数,让更多服务器保存chunk,或者让可控制的大量客户端错开时间访问。


 

元数据

master上保存的元数据主要为:文件名到Chunk ID或者Chunk Handle数组的对应。

   第二个表单记录了Chunk ID到Chunk数据的对应关系这里的数据又包括了

每个Chunk存储在哪些服务器上,所以这部分是Chunk服务器的列表

每个Chunk当前的版本号,所以Master节点必须记住每个Chunk对应的版本号。

所有对于Chunk的写操作都必须在主Chunk(Primary Chunk)上顺序处理,主Chunk是Chunk的多个副本之一。所以,Master节点必须记住哪个Chunk服务器持有主Chunk

并且,主Chunk只能在特定的租约时间内担任主Chunk,所以,Master节点要记住主Chunk的租约过期时间。 

以上数据都存储在内存中,如果Master故障了,这些数据就都丢失了。为了能让Master重启而不丢失数据,Master节点会同时将数据存储在磁盘上。所以Master节点读数据只会从内存读,但是写数据的时候,至少有一部分数据会接入到磁盘中。

更具体来说,Master会在磁盘上存储log,每次有数据变更时,Master会在磁盘的log中追加一条记录,并生成CheckPoint(类似于备份点)。

 


 

不是所有的数据都要进行持久化

Chunk Handle的数组(第一个表单)要保存在磁盘上。我给它标记成NV(non-volatile, 非易失),这个标记表示对应的数据会写入到磁盘

Chunk服务器列表不用保存到磁盘上。因为Master节点重启之后可以与所有的Chunk server通信,并查询每个Chunk server存储了哪些Chunk,所以不用写入磁盘。

版本号要不要写入磁盘取决于GFS是如何工作的,我认为它需要写入磁盘。我们之后在讨论系统是如何工作的时候再详细讨论这个问题。这里先标记成NV。

主Chunk的ID,几乎可以确定不用写入磁盘,因为Master节点重启之后会忘记谁是主Chunk,它只需要等待60秒租约到期,那么它知道对于这个Chunk来说没有主Chunk,这个时候,Master节点可以安全指定一个新的主Chunk。所以这里标记成V。

类似的,租约过期时间也不用写入磁盘,所以这里标记成V。 

需要新增一个Chunk或者由于指定了新的主Chunk而导致版本号更新了,Master节点需要向磁盘中的Log追加一条记录说,我刚刚向这个文件添加了一个新的Chunk或者我刚刚修改了Chunk的版本号。


 

读文件

读请求来说,意味着应用程序或者GFS客户端有一个文件名和它想从文件的某个位置读取的偏移量(offset),应用程序会将这些信息发送给Master节点。Master节点会从自己的file表单中查询文件名,得到Chunk ID的数组。因为每个Chunk是64MB,所以偏移量除以64MB就可以从数组中得到对应的Chunk ID。之后Master再从Chunk表单中找到存有Chunk的服务器列表,并将列表返回给客户端。所以,第一步是客户端(或者应用程序)将文件名和偏移量发送给Master。第二步,Master节点将Chunk Handle(也就是ID,记为H)和服务器列表发送给客户端。

客户端会与选出的Chunk服务器通信,将Chunk Handle和偏移量发送给那个Chunk服务器。Chunk服务器会在本地的硬盘上,将每个Chunk存储成独立的Linux文件,并通过普通的Linux文件系统管理。并且可以推测,Chunk文件会按照Handle(也就是ID)命名。所以,Chunk服务器需要做的就是根据文件名找到对应的Chunk文件,之后从文件中读取对应的数据段,并将数据返回给客户端。

 

写文件:

  • 1)客户端会去问Master要写入的数据应该在哪些ChunkServer上。

    2)Master会告诉客户端数据可以写入的副本位置信息,还要告诉客户端哪个是主副本Primary Replica,数据此时以主副本Primary Replica为准。

    3)客户端拿到副本位置信息后,即:应该写入哪些ChunkServer里,客户端会把要写入的数据发送给所有副本。此时ChunkServer把接收到的数据放在一个LRU缓存中,并不真正地写数据。

    4)等所有次副本Secondary Replica都接收完数据后,客户端就会给主副本Primary Replica发送一个写请求。因为客户端有成百上千个,会产生并发的写请求,因此主副本Primary Replica有可能收到很多客户端的写请求,主副本Primary Replica会将这些写请求排序,确保所有数据的写入是按照一个固定的顺序。主副本Primary Replica将LRU缓存中的数据写入实际的Chunk里。

    5)主副本Primary Replica把写请求发送给所有的次副本Secondary Replica,次副本Secondary Replica会和主副本Primary Replica以同样的数据写入顺序,将数据写入磁盘。

    6)次副本Secondary Replica数据写完后,将回复主副本Primary Replica写入完毕。

    7)主副本Primary Replica再去告诉客户端,这次数据写入成功了。如果有某个副本写入失败,也会告诉客户端,本次数据写入失败了。

    由上面的数据写入过程可知,因为数据是写入到不同的ChunkServer上,这就会出现部分写入成功,部分写入失败的情况,这就涉及到数据的一致性问题,这个我们在“根据应用做设计取舍”里再分析,这里我们集中分析“根据硬件特性做设计”,怎么体现的这一点呢?我们看数据的复制流程:

     

     

    为了提高日志写入效率,并没有将日志写入数据库,而是写入文件,并在末尾追加。因为数据库是每一个数据在磁盘随机写入效率低。
    当Master节点故障重启,并重建它的状态,你不会想要从log的最开始重建状态,因为log的最开始可能是几年之前,所以Master节点会在磁盘中创建一些checkpoint点,这可能要花费几秒甚至一分钟。这样Master节点重启时,会从log中的最近一个checkpoint开始恢复,再逐条执行从Checkpoint开始的log,最后恢复自己的状态。

     
     
    一致性问题:
    当我们追加数据时,面对Chunk的三个副本,当客户端发送了一个追加数据的请求,要将数据A追加到文件末尾,所有的三个副本,包括一个Primary和两个Secondary,都成功的将数据追加到了Chunk,所以Chunk中的第一个记录是A。

     

     假设第二个客户端加入进来,想要追加数据B,但是由于网络问题发送给某个副本的消息丢失了。所以,追加数据B的消息只被两个副本收到,一个是Primary,一个是Secondary。这两个副本都在文件中追加了数据B,所以,现在我们有两个副本有数据B,另一个没有。

     

     之后,第三个客户端想要追加数据C,并且第三个客户端记得下图中左边第一个副本是Primary。Primary选择了偏移量,并将偏移量告诉Secondary,将数据C写在Chunk的这个位置。三个副本都将数据C写在这个位置。

     

     对于数据B来说,客户端会收到写入失败的回复,客户端会重发写入数据B的请求。所以,第二个客户端会再次请求追加数据B,或许这次数据没有在网络中丢包,并且所有的三个副本都成功追加了数据B。现在三个副本都在线,并且都有最新的版本号。

     

     

    之后,如果一个客户端读文件,读到的内容取决于读取的是Chunk的哪个副本。客户端总共可以看到三条数据,但是取决于不同的副本,读取数据的顺序是不一样的。如果读取的是第一个副本,那么客户端可以读到A、B、C,然后是一个重复的B。如果读取的是第三个副本,那么客户端可以读到A,一个空白数据,然后是C、B。所以,如果读取前两个副本,B和C的顺序是先B后C,如果读的是第三个副本,B和C的顺序是先C后B。所以,不同的读请求可能得到不同的结果。

    或许最坏的情况是,一些客户端写文件时,因为其中一个Secondary未能成功执行数据追加操作,客户端从Primary收到写入失败的回复。在客户端重新发送写文件请求之前,客户端就故障了。所以,你有可能进入这种情形:数据D出现在某些副本中,而其他副本则完全没有。

     

     在GFS的这种工作方式下,如果Primary返回写入成功,那么一切都还好,如果Primary返回写入失败,就不是那么好了。Primary返回写入失败会导致不同的副本有完全不同的数据。

posted on   thotf  阅读(451)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示