分布式学习:GFS

master不记录哪些chunkserver拥有特定chunk副本,只在启动时轮询获得该信息,并通过定期的heartbeat消息监控所有chunkserver的状态

操作日志:包含元数据更改的历史记录,以及并发操作顺序的逻辑时间线(由此标记文件和块的版本号),只有将日志更新到本地和远程磁盘后,才能响应客户端操作,日志的作用:让master通过重放日志恢复GFS状态,为了缩短启动时间,master会对状态设置检查点(在不延迟接收到的新操作的情况下,切换到一个新的日志文件,并在一个单独的线程中创建检查点)

数据突变:写入:在应用程序指定的偏移位置写入数据;追加:在客户端认为是当前文件末尾的偏移位置写入,为了适应宽松的一致性模型,所有的应用都是通过追加来改变文件的,并且writers预处理每条记录都包含校验和等额外信息,readers使用校验和识别并丢弃,且可以使用记录中的唯一标识符过滤重复的数据

每个chunk有三个副本,每次突变都会在该chunk的所有副本中执行,master会选择其中一个作为primary,初始租约时间为60s,其余三个是secondaries,master可以通过heartbeat报文提前终止或在租约到期后重新选取新primary

当master选择好一个primary后,将会更新该primary的版本号,然后通知primary和secondaries也将版本号持久化到磁盘上(只有在master重新选择primary时,版本号才会增加)

当master创建一个chunk时,尽量在不同的机架上分布,并且尽量放在磁盘空间利用率较低的chunk server上

当可用chunk副本的数量低于用户所期望的数量时,master会选择重新复制chunk创建副本,并且优先复制那些副本数量远低于期望值、仍在使用(而不是被lazy deleted)的chunk,这个复制操作与创建chunk的操作基本一致

最后,master会周期性地平衡副本,对当前的副本分布进行排序,以获得更好的磁盘空间和负载平衡

master

用来管理文件和chunk的信息,最主要的是维护了两个表单

  • 文件名到chunk id数组的对应(也就是文件对应了哪些chunk):非易失

  • chunk id到chunk数据的对应关系

    • chunk server的列表(每个chunk存储在哪些server上)

    • 每个chunk当前的版本号:非易失

      如果版本号在故障后丢失,master就无法判断哪些chunk server上的数据是陈旧的,哪些server的数据是最新的

    • 哪个chunk当前持有primary租约

    • chunk的primary租约的过期时间

以上的数据全部存储在内存中,为了防止故障丢失信息,master在读数据时从内存读取,但写数据时会将一部分数据持久化到磁盘:存储log,记录每次的数据变更,并定期生成检查点

写入操作

 

  1. client询问master:哪个chunkserver拥有该chunk的当前租约,以及其他secondaries的位置;(若没有租约,主服务器会选择一个)

  2. master恢复primary和secondaries的位置,client缓存这些数据

  3. client向所有chunkserver推送数据,以链式线性方式,而不是其他拓扑结构推送,且为了避免网络瓶颈,每台收到数据的chunkserver会将数据转发给离它最近但未收到数据的chunkserver,并且在TCP连接上对数据传输进行管道化处理:也就是一旦一个chunkserver收到数据,它就立刻开始转发

  4. 当所有的chunkserver都确认收到数据后,client向primary发送写请求,primary为它接收到的所有突变分配连续的序列号,并将突变保存到自己的状态

  5. primary向所有secondaries转发写请求

  6. 每个secondaries都会回复一次primary,以表示它们完成操作

  7. master回复client写入结果,如果有一个副本失败即回复失败,client会重试失败的突变

但在这种传统的写操作中,对同一个区域的并发写入是不可序列化的,该区域可能会包含来自多个客户端的数据片段,如果对数据的连续性有所要求,可以考虑使用追加操作

追加操作

client只指定数据,而GFS会在它所选择的偏移位置将数据原子地追加到文件中至少一次,会返回偏移量给client

追加操作遵循写操作的控制流,client将数据推送到文件末尾最后一块chunk的所有servers上,primary会判断将记录追加到当前chunk是否会超出最大容量64MB,如果会:它将当前chunk填充到最大大小,然后让client在一个chunk上重试;如果不会则将数据追加到副本中

读取操作

client将文件名和偏移量发送给master,master将chunk id和对应的server列表返回给client,client会选择网络上最近的一个server发送chunk id和偏移量,chunk server在本地磁盘上将每个chunk存储为独立的linux文件,它将根据文件名找到对应的chunk并返回client期望的数据段

同时由于client可能多次连续读,所以client会缓存chunk和server的对应关系,方便再次读取相同chunk的数据

如果读取的数据超过了一个chunk或者说一次读操作跨越了chunk的边界时,客户端的链接库会意识到这一点,并将一个读请求拆分成两个读请求再发送到master

删除操作

当应用程序删除文件后,master会重命名文件为一个包含删除时间戳的隐藏名称,这时候该文件仍然可以以特殊名称读取,也可以通过重命名它来取消删除

直到当master定期扫描文件空间时,才会真正地删除一些文件(消除内存中的元数据)

  • 删除已经存在超过一定间隔的隐藏文件

  • 删除无法从任何文件中找到的chunk

  • 删除版本号过期的chunk副本

每个chunk server则会在与master定期交换的heartbeat消息中,报告它们所拥有的chunk子集,而master会回复它们那些已经被删除的chunk是什么,chunk server可以自行删除它们

master所未知的任何chunk都属于"垃圾"

这种方式的垃圾回收,具有以下优点:1.提供一种统一可靠的方式来清理副本;2.将垃圾回收操作合并到了master的常规后台活动中(比如在定期扫描文件空间时删除chunk元数据;比如在定期与chunk server的heartbeat消息中通知哪些副本已删除)3. 这种方式避免了一些意外的不可逆的删除

同时,如果某些删除文件被再次明确删除,master将会加快垃圾回收,且允许用户对文件空间的不同部分使用不同的复制和回收策略

posted @ 2023-09-20 16:33  pinoky  阅读(59)  评论(4编辑  收藏  举报