vlambda博客
学习文章列表

探索GPS与HDFS的设计理念

1 GPS

GPS(Google File System),Google为存储海量搜索数据而设计的专用文件系统。其设计原则如下:

1.硬件特性进行设计取舍:采用流水线式的数据传输,而非树形;文件复制时,直接在本地拷贝。减少数据在网络上的传输,避免网络带宽成为瓶颈;

2.简单:使用 Linux 服务上的普通文件作为基础存储层,并且选择了最简单的单Master 设计。一旦 Master 出现故障,整个集群就无法写入数据(算不上高可用),虽然有Backup Master的存在,但是从检测到,读取最新CheckPoint,重放日志,可能是分钟级别的,这期间仍旧是不可用的;

3.数据一致性:GFS在并发的随机写入中是一致但非确定的。而对于并发的追加写入,也只是做出了“至少一次”的保证。

1.1 单Master架构

Master的设计主要实现三个用途:存储目录基于存储数据的chunkserver;同步复制的主从架构下的主节点;相对于为了保障读数据的可用性而设立的 Shadow Master,它是一个异步复制的主从架构下的主节点。

存储目录,master 里面会存放三种主要的元数据:

1.文件和 chunk 的命名空间信息,即是路径和文件名。
2.这些文件被拆分成了哪几个 chunk(每一个chuck都有唯一对应的chunk handle编号),即是文件到多个chunk handle的映射。
3.这些 chunk 实际被存储在了哪些 chunkserver 上,也就是 chunk handle 到chunkserver 的映射关系。

通过这三种元数据,master可以找到客户端要读取的数据在哪里,返回给客户端。

而在HDFS中,NameNode即是第一关系和第二关系。

第一关系:文件与block数据块(chuck)的关系。
第二关系:数据块与数据节点的映射关系。

master的快速恢复和可用性

master接受所有客户端的查询请求,且只有一个节点,所以为保证master的性能,将master的数据都保存在内存中。

为了解决挂掉后,数据丢失的风险,master 会通过记录操作日志和定期生成对应的 Checkpoints 进行持久化。(挂掉后,重启读取Checkpoints 和 日志即可

Backup Master

如果master节点真的硬件出现故障,这时候需要快速恢复,即是Backup Master,它会进行同步复制。只有当数据在 master 上操作成功,对应的操作记录刷新到硬盘上,并且这几个 Backup Master 的数据也写入成功,并把操作记录刷新到硬盘上,整个操作才会被视为操作成功。当当前master挂掉后,会从Backup Master中选出一个即为新的master。

Shadow Master

在新的master选举成功,并读取Checkpoints 和 日志时,仍旧是一个空档期,因此为解决这个问题,并诞生了异步复制的Shadow Master,尽可能保持追上 master 的最新状态。

客户端只有在以下三种情况下会读到过时的master信息

1.master 挂掉了;
2.是挂掉的 master 或者 Backup Master 上的 Checkpoints 和操作日志,还没
有被影子 Master 同步完;
3.要读取的内容,恰恰是在没有同步完的那部分操作上。
HDFS中为了减少NameNode的压力,设计出Secondary NameNode来帮助其合并产生新的fsimage

1.2 根据硬件进行优化设计

分离控制流和数据流

实际的数据读写都不需要通过 master,客户端无论读写都只需要拿到master的元数据即可。(具体可看HDFS)。

流水线式的网络数据传输

如果用树形,同时对三个副本进行网络发送,master的带宽可以占满,但是三个chuckserver的数据只占用了1/3。如果用流水线式数据传输,能充分的利用带宽。

GFS中在传输时有主副本,GFS面对几百个并发的客户端,将传输过来的数据放在缓冲区,主副本进行排序,次副本以同样的顺序写入。

HDFS写入时不允许并发,因此在写入时也不用考虑太多,也无主副本之说,但是在租约恢复时会选出一个主副本,保证一致性。


那么为什么优先选择最近的副本写入,而非主副本?

这一点就和网络架构中的交换机相关了,如下图。

探索GPS与HDFS的设计理念

同一个机架Rack上的服务器都会接入一台接入层交换机(Access Switch);各个机架上的接入层交换机都会连接到一台汇聚层交换机(Aggregation Switch);汇聚层交换机会再连接到核心交换机(Core Switch);减少交换机的占用资源。由图可以知道,如果由客户端到B再传输给A,将会比由客户端到A再到B经过的交换机更多。


由此:Snapshot文件的复制会直接在本地拷贝,不会进行网络传输进行拷贝。

1.3 保证数据一致性设计

GFS中的“ 一致性”

第一个,就指“一致的(Consistent)”:多个客户端无论是从主副本读取数据,还是从次副本读取数据,读到的数据都是一样的。

第二个,指“确定的(Defined)”:就是客户端写入的数据能够完整地被读到。即:每个客户端写入指定offset的数据 和 再从offset读出来的数据是相同的。

GFS中的一个表格

探索GPS与HDFS的设计理念

随机写入

多个客户端并发写入数据,即使写入成功了,GFS 里的数据也可能会进入一个一致但是非确定的状态。如果客户端写入GFS中指定offset,客户端A写入数据范围[50, 80],客户端B写入数据范围[70, 100],就有可能出现B覆盖A,或者A覆盖B的情况(不确定的)(写入大小是不确定的)。但是三个副本按同样的顺序写入,是一致的。

出现的原因:

数据的写入顺序并不需要通过Master来协调,而是直接发送给ChunkServer,由ChunkServer来管理数据的写入顺序;记录追加Record Append的“至少一次”的保障。

只是进行追加将不会产生不确定的情况A、B、C各自的结尾处写入对应的数据。A客户端可以读取A的完整数据,同理BC一样。

如果副本写入失败,怎么办?

如下:

失败后,X会重新在后面进行记录追加(不止失败的副本)。

记录追加使得大部分数据都是一致的,并且是确定的,但是整个文件中,会夹杂着少数不一致也不确定的数据。(保证了至少一次,但不保证顺序。可能使得客户端拿到重复的数据和空数据)(Google的网页存储并不在乎网页是存储了两遍,还是两个网页的顺序)。

但是我们可以在客户端处进行解决,比如在数据中加入校验和,加入唯一的包含时间戳的ID。这样我们可以进行进一步的去重或者排序的操作。

注:GFS 限制了一次记录追加的数据量是16MB,而 chunkserver 里的一个 chunk 的大小是 64MB。所以,在记录追加需要在chunk 里填空数据的时候,最多也就是填入 16MB,也就是 chunkserver 的存储空间最多会浪费 1/4。GFS的至少一次保证了高并发和高性能。


在HDFS中,不允许并发且只能追加,也就没有了原来的复杂步骤(如主副本的排序),这样同时保证了一致和确定的。如果是客户端故障,为保证一致性,会进行租约恢复。

如果是DataNode出现问题,分为三种情况:

1.从 pipeline setup(准备阶段) 错误中恢复:

新写文件:Client 重新请求 NameNode 分配 block 和 DataNodes,重新设置 pipeline。
追加文件:Client 从 pipeline 中移除出错的 DataNode,然后继续。

2.从 close 错误中恢复:

到了 close 阶段才出错,实际数据已经全部写入了 DataNodes 中,所以影响很小了。Client 依然根据剩下正常的 DataNode 重建 pipeline,让剩下的 DataNode 继续完成 close 阶段需要做的工作。

3.当 pipeline 中一个 DataNode 挂了,Client 重建 pipeline 时是可以移除挂了的 DataNode,也可以使用新的 DataNode 来替换。这里有策略是可配置的,称为 DataNode Replacement Policy upon Failure,包括下面几种情况:

1.NEVER:从不替换,针对 Client 的行为
2.DISABLE:禁止替换,DataNode 服务端抛出异常,表现行为类似 Client 的 NEVER 策略
3.DEFAULT:默认根据副本数要求来决定,简单来说若配置的副本数为 3,如果坏了 2 个 DataNode,则会替换,否则不替换
4.ALWAYS:总是替换。
5.HDFS会每6小时进行检测,然后进行数据块的恢复。

    



原文链接

https://blog.csdn.net/qq_52142181/article/details/123003028?spm=1001.2014.3001.5501