简易分布式存储系统设计基础模块(二) | 青训营笔记

74 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第7天,今天分享一下写简易分布式存储系统设计的一些心得,这是我们项目的GitHUb地址,欢迎大家批评指导: liuzongzhou/GoDFS (github.com)

1、详细设计

1.Mkdir:创建目录

Mkdir流程.jpg 首先会获取当前存活的datanode元数据组信息,如果没有存活的节点或者存活的节点连接失败会直接返回err,对获取到的所有有效dataNode实例,使用rpc调用创建相应的目录。

2.Put:上传文件

Put流程.jpg 首先查看文件元信息,文件不存在或者路径有问题,直接返回false。rpc调用nameNode的Service.WriteData方法,获取写入请求的元数据数组,包含每个BlockId对应的主dataNode和多个备份remainingDataNodes。rpc调用dataNode的Service.PutData方法实现对主从dataNode的元数据写入。

特殊设计点:

  • 实现多副本的一致性写,nameNode负责写入主副本,副本的数据信息从主副本异步拉取。
  • 实现了负载均衡的存储策略,随机选择存储节点,尽量做到负载均衡。

3.Get:下载文件

Get流程.jpg 首先通过文件的绝对路径去nameNode查询文件的元数据信息,通过远程调用nameNode的Service.ReadData方法得到NameNodeMetaData,其中包含了文件的blockId和blockAddress,通过blockAddress创建nameNodeInstance,调用nameNode的Service.GetData方法,传入文件的路径和blockId,如此往复,指导获取所有block块为止。

特殊设计点:

  • 支持存储节点单节点故障时,不阻塞已有数据的读取。

在NameNodeMetaData中,我们会得到文件每个block所在的所有nameNode节点信息,当从主dataNode节点读取成功,直接进行下个block的读取,当从主dataNode节点读取失败,我们会读取其他dataNode节点的备份信息。

4.Delete:删除文件或者删除目录及所有子文件

DeletePath

DeletePath流程.jpg 首先取得当前存活的所有dataNodes节点信息,构造nameNode实例,向所有存活dataNode发起删除目录的rpc请求,当所有的dataNode上路径删除均成功时,才会删除nameNode上存储的元数据信息。

  • 实现了防止dataNode出现脏数据的功能 即首先删除dataNode的数据信息,再删除nameNode的元数据信息,当删除在某个节点失败时,由于元数据信息不丢失,只要重新删除即可。

DeleteFile

DeleteFile流程.jpg 首先取得需要删除文件的元数据信息,通过rpc调用nameNode实例的Service.ReadData方法得到文件的BlockIds和对应的BlockAddresses,通过BlockAddresses构造nameNode实例,向存活dataNode发起删除对应BlockId文件的rpc请求,当所有的dataNode上的Block块删除均成功时,才会删除nameNode上存储的元数据信息。

特殊设计点:

  • 实现了防止dataNode出现脏数据的功能

即首先删除dataNode的数据信息,再删除nameNode的元数据信息,当删除在某个节点失败时,由于元数据信息不丢失,只要重新删除即可。

  • 处理了当删除过程中nameNode节点死亡的特殊情况,当某个nameNode连接不上时,会删除其他nameNode的数据,并不会报错。

本次介绍就到这里,下次继续介绍stat、rename、list接口设计和开发。