MIT 6.824 Lecture 3 - GFS

MIT 6.824 Lecture 2 - GFS

GFS(谷歌文件系统)是一个可扩展的分布式文件系统,用于大型的、分布式的、对大量数据进行访问的应用。它运行于廉价的普通硬件上,并提供容错功能。它可以给大量的用户提供总体性能较高的服务。

本章节主要讨论点:

  • storage:存储
  • GFS:GFS的设计
  • consistency:一致性

存储系统

难点

  • 高性能(high perference)

    • 分片
    • 跨多个服务机器存储数据
  • 多实例/多机器

    • 单机故障率低,但是足够多的机器则出现部分故障的概率高,在GFS论文上千台机器规模下,每天总会有3个机器出现失败/故障。因此需要有容错设计
  • 容错

    • replication:通常通过复制数据保证容错性,即当前磁盘数据异常/缺失等情况,尝试从另一个磁盘获取数据
  • 复制(replication)

    • potential inconsistencies:潜在的数据不一致问题需要考虑
  • 强一致性(strong consistency):

    • lower performance:一般需要通过一些消息机制保证一致性,这会稍微带来一些性能影响,但一般底层为了保证数据一致性而额外进行的网络通信等操作在整体性能的开销中占比并不会很高。其中可能涉及需要将通信的一些结果写入存储中,这是相对昂贵的操作。

一致性

​ 理想的一致性,即整个分布式系统对外表现时像单个机器一样运作。

​ 并发性(concurrency)和故障/失败(failures)是两个实现一致性时需要考虑的难点。

GFS

旨在保持高性能,这意味着他使用了复制和容错,但很难保持一致性google确实曾使用GFS,虽然后继被新的文件系统Colossus取代。

GFS有以下特征:

  • 大量的数据
  • 自动分片到多个磁盘
  • 所有应用程序从GFS读取数据时看到相同的文件(一致性)
  • 尽可能自动地采取一些容错恢复操作

GFS数据读取流程

在这里插入图片描述
体系结构

  • chunkserver提供存储。GFS会将文件划分为定长数据块,每个数据块都有一个全局唯一不可变的id(chunk_handle),数据块以普通Linux文件的形式存储在chunkserver上,出于可靠性考虑,每个数据块会存储多个副本,分布在不同chunkserver
  • GFS master就是GFS的元数据服务器,负责维护文件系统的元数据,包括命名空间、访问控制、文件-块映射、块地址等,以及控制系统级活动,如垃圾回收、负载均衡等。
  • 应用需要链接client的代码,然后client作为代理与master和chunkserver交互。master会定期与chunkserver交流(心跳),以获取chunkserver的状态并发送指令。图1还描述了应用读取数据的流程。

GPS通过Master管理文件系统的数据,其他Client只能往GFS写入或读取数据。当应用通过GFS Client读取数据时:

  1. Client向Master发起读数据请求
  2. Master查询(文件名->块的映射)数据对应的目录等信息,汇总文件块访问句柄、文件所在服务器的节点信息给Client(一个大文件会被拆分成多个chunk放到不同服务器上,一个chunk64M)
  3. Client得知这些chunk的信息后,直接和这些拥有chunk的服务器通信传输chunks

GFS-Master的工作

  • 维护file name->chunk handles块句柄数组的映射
  • 维护每一个块句柄的version
  • 维护块存储服务器列表
  • log+check point:先将操作存在log中,后续再响应Client。这样即使Master崩溃,也能通过log恢复。master会定期创建自己状态的检查点,落到持久性存储上,重启/恢复状态时只需重放log中最后一个check point检查点之后的所有操作,所以恢复也很快。

​ 这里需要思考的是,哪些数据需要放到稳定的存储中(比如磁盘)?

  • 比如file name => chunk hanles的映射,平时已经在内存中存储了,还有必要存在稳定的存储中吗?

需要,否则崩溃后恢复时,内存数据丢失,master无法索引某个具体的文件,相当于丢失了文件。

  • chunk handle 到 存放chunk的服务器列表,这一层映射关系,master需要稳定存储吗?

不需要,master重启时会要求其他存储chunk数据的服务器说明自己维护的chunk handles数据。这里master只需要内存中维护即可。同样的,主服务器(primary)、次要服务器(secondaries)、主服务器(primary)的租赁时间(lease time)也都只需要在内存中即可。

  • chunk handle的version版本号信息呢,master需要稳定存储吗?

需要。否则master崩溃重启时,master无法区分哪些chunk server存储的chunk最新的。比如可能有服务器存储的chunk version是14,由于网络问题,该服务器还没有拿到最新version 15的数据,master必须能够区分哪些server有最新version的chunk。

GFS-文件读取

  1. Client向Master发请求,要求读取X文件的Y偏移量的数据

  2. Master回复Client,X文件Y偏移量相关的块句柄、块服务器列表、版本号(chunk handle, list of chunk servers, version)

  3. Client 缓存cache块服务器列表(list of chunk servers):我们希望减少Client和Server之间的通信次数,客户端缓存可以大大减少Master机器的负载

  4. Client从最近的服务器请求chunk数据(reads from closest servers):因为这样在宛如拓扑结构的网络中可以最大限度地减少网络流量(mininize network traffic),提高整体系统的吞吐量。

  5. 被Client访问的chunk server检查version,version正确则返回数据:避免读取到过时的数据

关于第四点,我的理解是:我的理解就是:通过最近的服务器去请求数据,然后改服务器再去找对应chunk所在的服务器,能够保证走的总链路最短吧。(路由和负载均衡)。当然也可以有数据复制和数据缓存,但通过课上讲的,数据被被分成许多chunk分布在不同的服务器上,应该不是数据复制,而数据缓存是有可能的,将最近客户端访问过的数据缓存一次,这样下一次就不必访问远程服务器了。 GFS的客户端和chunkserver都不会缓存任何数据,这是因为GFS的典型应用是顺序访问大文件,不存在时间局部性。空间局部性虽然存在,但是数据集一般很大,以致没有足够的空间缓存。

GFS-文件写入

这里主要关注文件写入中的append操作,因为把记录追加到文件中这个在他们的业务中很常见。在mapreduce中,reducer将处理后的记录数据(计算结果)很快地追加(append)到file中

在分布式系统中,“primary"和"secondary"通常用来描述备份和冗余机制。这些术语指的是系统中的两个实体或角色,其中一个被标记为"primary”(主节点),而另一个被标记为"secondary"(辅助节点)。

  • 主要节点(primary)负责处理客户端请求和执行关键任务。它是系统的核心,并且具有所有权威性和控制权。主节点通常是活跃的,能够提供服务并保持数据的最新状态。

  • 次要节点(secondary)作为主节点的备份,用于提供冗余和故障恢复。它们通常处于待命状态,等待主节点发生故障或不可用时接管其职责。当主节点失效时,次要节点会接管主节点的功能,确保系统的连续性和可用性。

在这里插入图片描述

下面是文件写入的步骤

  1. Client向Master发出请求,查询应该往哪里写入filename对应的文件。

  2. Master查询filename到chunk handle映射关系的表,找到需要修改的chunk handle后,再查询chunk handle到chunk server数组映射关系的表,以list of chunk servers(primary、secondaries、version信息)作为Client请求的响应结果(减少Master的负担,不再和Master交互)
    接下去有两种情况,已有primary(主要节点)和没有primary(假设这是系统刚启动后不久,还没有primary)

    • 有primary
      继续后续流程
    • 无primary
      • master在chunk servers中选出一个作为primary,其余的chunk server作为secondaries。(暂时不考虑选出的细节和步骤)
        master会增加version(每次有新的primary时,都需要考虑时进入了一个new epoch,所以需要维护新的version),然后向primary和secondaries发送新的version,并且会发给primary有效期限的租约lease。这里primary和secondaries需要将version存储到磁盘,否则重启后内存数据丢失,无法让master信服自己拥有最新version的数据(同理Master也是将version存储在磁盘中)。
  3. Client发送数据到想写入的chunk servers(primary和secondaries),有趣的是,这里Client只需访问最近的secondary,而这个被访问的secondary会将数据也转发到列表中的下一个chunk server,此时数据还不会真正被chunk severs存储。(即上图中间黑色粗箭头,secondary收到数据后,马上将数据推送到其他本次需要写的chunk server)
    这么做提高了Client的吞吐量,避免Client本身需要消耗大量网络接口资源往primary和多个secondaries都发送数据。

  4. 数据传递完毕后,Client向primary发送一个message,表明本次为append操作。

    primary此时需要做几件事:

     1. primary此时会检查version,如果version不匹配,那么Client的操作会被拒绝
     2. primary检查lease是否还有效,如果自己的lease无效了,则不再接受任何mutation operations(因为租约无效时,外部可能已经存在一个新的primary了)
     3. 如果version、lease都有效,那么primary会选择一个offset用于写入
     4. primary将前面接收到的数据写入稳定存储中
    
  5. primary发送消息到secondaries,表示需要将之前接收的数据写入指定的offset(偏移量)

  6. secondaries写入数据到primary指定的offset中,并回应primary已完成数据写入

  7. primary回应Client,你想append追加的数据已完成写入(此时才会写入,之前第三步只是传输数据)


问题:写入流程中提到需要校验version,是否存在场景就是Client要读取旧version的数据?比如Client自己存储的version就是旧版本,所以读取数据时,拥有旧version的chunk server反而能够响应数据

回答:假设这里有P(primary),S1(secondary 1),S2(secondary 2)和C(Client),S2由于网络等问题和P、S1断开联系,此时重新选出Primary(假设还是原本的P),version变为11,而S2断联所以还是version10的数据。一个本地cache了version10和list of chunk sevrers的Client正好直接从S2请求读取数据(因为S2最近),而S2的version和Client一致,所以直接读取到S2的数据。

问题:上面举例中,version更新后,不会推送到S2吗?即通知S2应该记录最新的version为11

回答:version版本递增是在master中维护的,version只会在选择新的primary的时候更新。论文中还提到serial number序列号的概念,不过这个和version无关,这个用于表示写入顺序。

一致性(consistency)

  • 某时刻起,M得不到和P之间的ping-pong通信的响应,什么时候Master会指向一个新的P?
    1. M比如等待P的lease到期,否则会出现两个P
    2. 此时可能有些Client还在和这个P交互

假设我们此时选出新P,有两个P同时存在,这种场景被称为脑裂(split-brain),此时会出现很多意料外的情况,比如数据写入顺序混乱等问题,严重的脑裂问题可能会导致系统最后出现两个Master。

Reference

笔记
谷歌技术"三宝"之GFS

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值