GFS

1. 提出背景

前面说过mapreduce中在reduce阶段生成的文件是存储在文件系统中的,可想而知,这个系统一定是非常庞大,能够存储海量的文件。
GFS 正是这样一个适用于大规模的数据相关应用的分布式文件系统。

2. 如何设计(设计目标)

GFS在google的设计中,除了性能,扩展性,可靠性,以及可用性之外,还具有以下的特征:

  • 首先这个系统是基于普通的硬件设备,所以要把节点的失效,文件的丢失认为是是一种正常的情况,既然如此,系统就必须具有容错处理,自动恢复的功能。
  • 其次按照google的业务量和数据的增长来看,文件都会非常的巨大,因此必须对大文件的处理进行优化。
  • 根据常规的操作方式和特性来看,在磁盘中顺序写比随机写要快得多,并且大部分文件都是只会在文件尾新增加数据,而很少修改已有数据的。大部分文件一旦写入,几乎就不会修改,并且一般都是顺序读取得。因此,追加操作是最重要的。

Q:插一句话为什么在磁盘中顺序读写比随机读写要快得多?
A:平均存取时间 = 寻道时间 + 旋转延迟时间(磁头定位到所在扇区的时间)+ 传输时间。顺序读写,主要时间花费在了传输时间;随机读写,需要多次寻道和旋转延迟。 答案不言而喻。

所以实际上很容易得出,gfs的目标就是集群、容错、大文件友好,易安装部署的目标,那么我们究竟是如何来实现的?

3. 架构设计

一个GFS集群由一个 master 和大量的 chunkserver 构成,并被许多客户(Client)访问。

Master维护文件系统所有的元数据(metadata),包括名字空间、访问控制信息、从文件到块的映射以及块的当前位置。Master定期通过HeartBeat消息与每一个 chunkserver通信,给chunkserver传递指令并收集它的状态。

我们可以理解成:文件会被分成固定的大小块,内容存储在不同的chunkserver上,其映射关系等保存在master中,当用户需要读取文件的时候,他会通过询问master,master会告知他各个文件块的chunserver的位置,用户就直接从这些chunserver上读取数据。

这一架构设计的,大大简化了我们的操作,master可以从全局的管理所有的chunck。但是同样会带来许多挑战:

  • 由于metadata是存放在内存中,一旦master故障怎么办?
  • chunckserver某个节点故障怎么办?

4. 可靠性

上面的问题实际上是在询问这样的架构设计,如何保证gfs的可靠性?
我认为:一切可靠性,最终都要考落地存储,以及副本。

首先,在master中是单节点的设计,这意味着master的内存大小决定了chunk的上限,论文中是很简单的通过增加master机器的内存来解决这个问题。很有意思,给的答案也是简单粗暴直接。
我们来看一下商业上面的应用,在hadoop中的hdfs,主要是通过namespace的区分来处理不同的master节点,简单来说,就是上层加上路由,通过对namespace的操作,来决定需要和哪个master节点进行交互。(hdfs称master为namenode)。

其次,如果master节点故障,内存中的数据岂不是会丢失? 上面说了,这个就依靠落地存储。在master中会保存一个日志(operation log,这个在hdfs中叫editlog)到本地磁盘,这一日志主要记录metadata的数据变化。并且当log的大小增长到一定的阶段,会执行一个checkpoint的动作。checkpoint是一个类似B树的结构,能直接映射到内存。

插一句话,这种操作跟redis中AOF方式落地有着异曲同工的意思。AOF也是在每次redis的操作会在日志中记录数据,同时在一定的阶段,会实现AOF重写操作。

当然,作为一个高可用的系统,必须要认为,即使文件落地在本地磁盘中,也是不可靠的。那么master即使把元数据落地到本地磁盘中,一旦机器故障,磁盘损坏,怎么办?
其实很简单,就是把上面说的操作日志和checkpoint复制到多个机器上,论文说的并不是很详细。我们看一下hdfs中是如何实现master的复制,并且在master故障后,如何快速的启用。

4.1 HDFS中namenode的高可用

副本文件的安全性,主要是通过副本的复制来保存,这个上面已经说了。
那么在某个正在运行的namenode故障,简单来说,就是通过zookeeper来监控,当出现问题的时候,通过选举出其中一个副本所在位置的namenode作为主namenode,另外其余的副本namenode可以做只读操作。
具体的内容可以参考这篇文章。https://www.cnblogs.com/hellochennan/p/5373177.html

这个方式让我想起,之前在做微信公众号开发的时候,微信的公众号中token必须是全局唯一的,token是通过rpc与其他的服务之间调用的,但是一旦token出现故障,就意味着这一系统有很大一部分处于不可用的状态。 我采取跟上面类似的方式,通过利用etcd注册token 服务,其余服务通过etcd来实现服务的发现,并且其中有一个备用的token服务,定时的ping 已经注册的token服务,通过这一方式,来实现token服务的高可用。

4.2 chunkserver的高可用

chunckserver的高可用性,实际上也是副本的复制来实现的。chunkserver的复制主要是发生以下三个状态。

  • 新创建chunk,当master新创建一个chunk的时候。
  • 当chunk出现错误的时候,低于用户指定的数量时,master会立刻尝试重新复制一个chunk副本。
  • master会定期的重新均衡副本的,主要时检查副本的情况,通过调整副本进行负载均衡(各chunkserver的磁盘空间)。

5. 结束语

我觉得写到这个地方GFS的基本逻辑已经很清晰,就是一个master多chunkserver,通过副本保证其高可用。但是中间还有很多的细节。
如:

  • 当请求文件的时候,我如何选择chunk副本,理论上来说肯定是选择离客户端最近的节点,但是这个算法是什么?
  • 在读取文件的时候,我们能否通过利用不同的副本位置,采用并行的方式去请求,如何处理?
  • 如何判断文件是否损坏?
  • 当写一个chunk的时候,每个变动都要对所有的chunk副本进行操作,如何保证其一致性?

.....

后面的我们通过一个大数据系列,通过对hadoop的解读来重读这个论文,感谢!

猜你喜欢

转载自www.cnblogs.com/songjingsong/p/9208825.html
GFS
今日推荐