GFS论文分析

一、背景

The Google File System, GFS论文发表在2003年,在该论文发表之前,工业界的分布式系统最多也就是几十台服务器的集群,而GFS提出了一个可管理1000台服务器以上的分布式文件系统,同时可以接受数百个客户端的并发请求。

二、架构设计特点

在这里插入图片描述

1、分布式文件系统利用了很多普通且廉价的服务器——>GFS容错机制完善、一致性很宽松。
容错机制包括:三副本、心跳机制、Backup Master和Shadow Master。
2、标准的X86服务器一般自带机械硬盘,寻道时延太长——>GFS提供了append write附加写方式。
3、设计目的是为了处理大批量的数据——>高性能的网络带宽比低时延重要——>GFS采用流水线式(pipeline)网络数据传输
4、单主模式,master节点只存储元信息
5、实际文件数据存储在chunkserver,按64MB分块,三副本

三、架构特点详解

1、Master节点

(1)Handler和Chunk

GFS将文件分割成固定大小的Chunk,在Chunk创建时,Master服务器会给每个Chunk分配一个不变的、全球唯一的64位标识——Handler句柄,Chunk Server把Chunk以普通Linux文件的形式保存在本地硬盘上,并且根据指定的Handler句柄和字节范围来读写数据。
Master节点维持整个集群的元信息,包括集群的名字空间Namespace、访问控制信息、文件和Chunk的映射信息、当前Chunk的位置信息、Chunk Lease的租约管理、Chunk回收、Chunk在服务器之间的迁移等系统级操作。
Master相当于Linux系统中的inode节点,只是更复杂,因为是分布式系统,所以把inode节点抽出来单独放到一个机器上。Client从Master拿到Handler,Handler相当于Linux中指向block的指针,Handler可以唯一标识一个Chunk,通过Hander找到要读取的数据块。

(2)Chunk位置信息

Master服务器并不持久化保存哪个Chunk服务器存有指定Chunk的副本的信息。
Master服务器只是在启动的时候轮询Chunk服务器以获取这些信息。
这种设计简化了在有Chunk服务器加入集群、离开集群、更名、失效、以及重启的时候,Master服务器和Chunk服务器数据同步的问题。在一个拥有数百台服务器的集群中,这类事件会频繁的发生。
可以从另外一个角度去理解这个设计决策:只有Chunk服务器才能最终确定一个Chunk是否在它的硬盘上。我们从没有考虑过在Master服务器上维护一个这些信息的全局视图,因为Chunk服务器的错误可能会导致Chunk自动消失(比如,硬盘损坏了或者无法访问了),亦或者操作人员可能会重命名一个Chunk服务器。

(3)Client怎么找到文件所在的Chunk Server的

Client查找Master的元信息metadata
The master stores three major types of metadata: the file and chunk namespaces, the mapping from files to chunks, and the locations of each chunk’s replicas.
1)文件和Chunk的命名空间信息,即:/data/bigdata/gfs01,这样的命名空间和文件名。
2)文件被拆分成了哪几个Chunk,即:命名空间文件名到多个Chunk Handle句柄的映射关系。
3)这些Chunk实际存储在了哪些Chunk Server上,即:Chunk Handle句柄到Chunk Server服务器的映射关系。
在这里插入图片描述

客户端读GFS的数据时,会把文件名和chunk index发送到Master上,因为Chunk大小固定,client可以将要读取的部分字节偏移转化成文件内的chunk index。master会回复相应的chunk handler和副本所在位置。client会缓存这些信息,key是文件名+chunk index。
client接下来会发请求到(一般是)最近的副本块,请求内容包括chunk handler和块内的字节偏移,之后的访问不再经过master节点。
client会缓存一些元信息来减少和master的交互,但client和chunkserver都不会缓存文件,client不缓存是因为文件太大需要的缓存空间太大,chunkserver不缓存是因为没必要,每个chunk存在本地,那些频繁访问的数据被存在了内存中。

(4)单主模式

GFS采用的是单主模式,为了设计上的简单,否则集群如果有两个master同时工作,会涉及到复杂的元信息同步问题。而且单主模式会使得master在做块的放置和复制的决定时可以掌握全局的信息, 所以GFS采用的是单主模式。
单主模式也带来了一些问题,因为只有一个master,所以必须考虑当master出现故障时系统的容错性。
为了避免master成为系统的瓶颈,必须尽量减少对master的访问,所以master上不存储任何的文件数据,减少了在读写过程中client对master的访问次数。

(5)单主模式的容错机制

1)Checkpoint和操作日志
Master的metadata是放在内存中的,所以一旦Master重启或者出故障,就会丢失。解决方法:通过记录操作日志和定期生成对应的Checkpoint进行持久化,也就是存储到磁盘上,这样就不怕内存因故障而数据丢失了。当Master重启时,就先读取最新的Checkpoint,然后进行回放(replay)操作日志,这样就可以让Master节点恢复到之前最新的状态,这就是存储系统常用的可恢复机制。
2)Backup Master
Checkpoint是可以应对Master重启立刻恢复服务的情况,但是如果Master出现故障无法恢复,就需要一个stand by的Master节点开始提供服务,这就是Backup Master。
所有针对Master的操作都同时写入Backup Master上,只有Master上操作成功且写入磁盘成功,还有Backup Master上也操作成功且写入磁盘成功,整个操作才视为成功。这种方式叫做“同步复制”,是分布式数据系统中一种典型的模式。(如高可用的Mysql一般都是主从架构的同步复制模式)
当Master节点故障后,Backup Master节点便会转正,变成新的Master,而里面的数据都是一摸一样的。
检测Master状态需要一个监控程序,监控Master服务的运行状态,如果只是master服务挂了,只要重启master服务;如果是Master节点故障,就选择一个Backup Master节点成为新Master。为了让集群中其他Chunk Server和客户端不用感知这个Master切换的变化,GFS通过一个规范名字(Canonical Name)来访问Master节点,这类似于DNS别名,这样,一旦要切换Master,这个监控程序只需要修改别名实际指向,访问新的Master节点就能达到目的。有了这个机制,GFS的Master就可快速恢复(Fast Recovery)。
3)影子节点Shadow Master
为了避免采用了Backup Master仍然出了故障,GFS又加入了一些只读的影子节点Shadow Master,这些Shadow Master于Backup Master节点不同的是,Master写入数据并不需要等待这些Shadow Master节点也写入成功,而是这些Shadow Master节点不断地从Master节点上同步数据,这种方式叫做“异步复制”,是分布式数据系统中另一种典型的模式。
在异步复制模式下,这些Shadow Master节点上的数据跟Master节点上的数据并不是完全同步的,而是可能有小小的延迟。这可能导致这些Shadow Master节点上元数据信息不是最新的。
但是读到Shadow Master上脏数据的情况可能性还是很小的,因为这需要同时满足三个条件:1)Master节点和Backup Master节点都挂掉;2)Shadow Master节点没有同步完最新的操作日志和Checkpoints;3)恰好要读取的那部分数据就是没有同步完的部分。
补救措施:为了防止在以上小概率情况下Shadow Master的同步不及时,Shadow Master会读取一份当前正在进行的操作日志副本,并依照跟Master完全相同的顺序更新内部数据。Shadow Master在启动时也会从Chunk Server服务器上轮询数据(之后定期拉数据),数据包括副本的位置信息。Shadow Master也会定期和Chunk Server服务器“握手”来确定他们的状态,只有在Master节点因为创建和删除副本导致副本的位置信息变化时,Shadow Master才和Master通信更新自身状态。
通过Backup Master和Shadow Master,GFS构建了高可用(HA)架构。
在这里插入图片描述

2、GFS读写数据

在GFS论文发表的年代,大部分用户还在使用机械硬盘,机械硬盘的随机读写性能太差,所以GFS的设计中主要是顺序读写操作,以Append追加的方式写入数据,以流式访问读取数据。
GFS是为了在廉价硬件上做大规模数据处理设计的,所以对一致性的要求很宽松,对随机写入的一致性没有任何保障,对于Append追加操作,GFS也是做了“At Least Once”至少一次的保障

(1)写入一致性

见另一篇博客GFS的写入一致性

(2)为什么chunk是64MB(新版本是128MB)

每个副本chunk被当作普通的linux文件存储,但是64MB比一般的文件系统块规模大的多,大的好处有三个:1)减少client和master交互 2)在一个给定块上可以执行多个操作,保持较长的tcp连接,可以减少网络负载。3)减少了master上metadata的规模,可以将metadata放在内存里。
以上的三个好处,出发点是减少master和网络负载,因为架构设计的结构原因,单主模式使得master容易成为瓶颈,大数据和大文件的处理对带宽要求很高。
大的数据块也有坏处:容易出现热点问题。解决方法是:给这些热点数据更多复本块数,并且错开应用的访问时间。也可以允许一个客户端从另外一个客户端读取数据(参考流水线式数据传输)

(3)lease——选定Primary Replica

GFS使用leases来保证多个chunk副本间数据改动的一致性。Master节点会授予某一个chunk副本chunk lease,被授予lease的chunk副本叫做primary。 primary会决定chunk上一系列改动操作的执行顺序(写请求排序),并且所有的副本都会按照这个顺序执行改动操作。 leases的初始期限是60s. 即使master与primary失去了联系,master也会在primary的leases过期之后安全的选择新的primary。

(4)文件复制Snapshot操作

Client通过Snapshot指令复制文件时,指令会通过控制流下发到主副本Primary Replica,主副本Primary Replica再下达到次副本Secondary Replica,然后各个副本所在的ChunkServer直接在本地复制一份对应的Chunk数据,这就避免了来回的网络传输问题。
snapshot操作可以对文件和目录树进行快速复制,并且最大限度的减少对正在执行的数据改动操作的影响。GFS使用copy-on-write技术来实现snapshots。 GFS对snapshot的处理机制如下所示:
1)client发送snapshot request,master收到request后,会回收需要进行snapshot文件的所有chunks的leases。
2)当leases被回收后,master将snapshot operation持久化记录在log中。随后,master根据log record来复制metadata或directory tree。新创建的snapshot files与源文件指向相同的chunks(写时复制)。
3)当client首次想要在snapshot operation后向chunk C写入数据时,它会向master发送request来寻找最新的lease holder。master发现chunk C的引用计数不止一个,便会推迟回复request并创建一个新的chunk handler C’。master随后通知所有chunk C的副本需要创建一个新的chunk C’。
4)创建完成后,master会随机挑选一个chunk C’的副本赋予其leases并答复client。
在这里插入图片描述
参考Snapshot流程

3、同步数据的网络传输

当时的数据中心服务器的网卡带宽普遍是百兆网卡,网络带宽往往是系统的性能瓶颈。而且GFS的设计目的是侧重于处理大批量数据,而不是对用户的请求实时响应,所以对于网络带宽的充分利用,相对于低时延来说,更为重要。
为了充分利用网络带宽,GFS采用了:1)流水线式的数据传输机制,2)Snapshot操作chunk的本地复制(如上三-2-(4))

4、GFS数据的写入过程

在这里插入图片描述

step1:Client访问Master获取要写入的数据所在ChunkServer的信息
step2:Master回复Client数据可以写入的副本位置,并告知哪个是主副本Primary Replica,数据此时以主副本Primary Replica为准。
step3:客户端拿到副本位置信息(应该写入哪些ChunkServer里)后,客户端会把要写入的数据发送给所有副本。此时ChunkServer把接收到的数据放在一个LRU缓存中,并不真正地写数据。
LRU,Least Recently Used算法,即一种缓存淘汰策略。LRU判定最近使用过的数据为有用的,很久都没用过的数据是无用的,在内存满了就优先删除很久未使用,也就是无用的数据。
step4:等所有次副本Secondary Replica都接收完数据后,客户端就会给主副本Primary Replica发送一个写请求。因为客户端有成百上千个,会产生并发的写请求,因此主副本Primary Replica有可能收到很多客户端的写请求,主副本Primary Replica会将这些写请求排序,确保所有数据的写入是按照一个固定的顺序。主副本Primary Replica将LRU缓存中的数据写入实际的Chunk里。
step5:主副本Primary Replica把写请求发送给所有的次副本Secondary Replica,次副本Secondary Replica会和主副本Primary Replica以同样的数据写入顺序,将数据写入磁盘。
step6:次副本Secondary Replica数据写完后,将回复主副本Primary Replica写入完毕。
step7:主副本Primary Replica再去告诉客户端,这次数据写入成功了。如果有某个副本写入失败,也会告诉客户端,本次数据写入失败了。
由上图可以得知,GFS写入过程的特点:1)控制流和数据流是分开的,2)数据流的复制过程是流水线式的。

(1)控制流和数据流的分离

Client只有在step1从Master节点上拿到了数据要写入的Chunk Server的信息,其他步骤如实际的数据传输不再经过Master节点。这样目的也是减轻Master的负载。

(2)数据流的流水线式复制过程

网络有可能成为系统的最大瓶颈,当Client发送数据时,如果之间发给所有的ChunkServer,客户端的出口网络会立刻成为性能瓶颈。如果只是让客户端一个一个的发,似乎还未收到数据的ChunkServer就只能被动等待,没有充分利用网络带宽,所以采用了流水线模式:
数据不一定是先给到主副本,而是看网络中离哪个ChunkServer更近,就给那个最近的ChunkServer,如上图所示,客户端先把数据传输到离自己网络最近的次副本Secondary Replica A上,而且次副本Secondary Replica A是一边接收客户端发来的数据,一边又把数据发送给离自己最近的主副本Primary Replica上,同理,主副本Primary Replica也是一边接收次副本Secondary Replica A发来的数据,一边又把数据发送给离自己最近的次副本Secondary Replica B,这就是流水线式的数据传输方式。
对比:客户端同时发送数据给所有ChunkServer和流水线式的发送数据。
在这里插入图片描述

为什么强调Client“先把数据传输到离自己网络最近的次副本Secondary Replica A上”,而不是直接发送给主副本Primary Replica呢?

在这里插入图片描述

如上图所示,数据中心有几百台服务器,通过三层网络连接起来:
1)同一个机架Rack上的服务器都会接入一台接入层交换机(Access Switch);
2)各个机架上的接入层交换机都会连接到一台汇聚层交换机(Aggregation Switch);
3)汇聚层交换机会再连接到核心交换机(Core Switch);
由此构成一个三层网络拓扑图,这样你就会发现:如果两台服务器在同一个机架Rack上,它们之间的网络传输只需要经过接入层交换机,即:除了两台服务器自身的网络带宽外,只会占用所在的接入层交换机的带宽。如果不在同一个机架上,甚至不在同一个VLAN内,就需要通过汇聚层交换机,甚至核心交换机,这个时候汇聚层交换机或核心交换机就有可能成为性能瓶颈。

参考文章:
04| GFS论文解读(1)
05| GFS论文解读(2)
分布式系统论文精读2:GFS

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值