AppBoxFuture(五): 分布式文件存储-Store Everything

  本来本篇是想介绍前端组件化开发用户界面,发现框架还未实现文件存储,原本计划是后续设计开发的,索性把计划提前,所以本篇将介绍基于Raft实现分布式的文件存储引擎。

一. 实现思路

  既然是分布式存储,就需要解决以下几个关键问题:

  • 如何将文件以多副本的形式存储在集群的节点上,且保证副本间的一致性?这个问题可基于Raft协议实现相应的状态机来解决;
  • 如何将大量的文件分组,即如何划分多个Raft组?这个问题可通过在目录元数据内保存多个Raft组信息,每个组存储限制在64M(暂定)来解决;
  • 如何存储与管理目录及文件的元数据?这个问题可通过实现元数据状态机来管理,利用已实现的KV存储引擎来存储元数据;
  • 如何保证元数据与文件数据的一致性?这个问题开始时想用已实现的EntityStore的事务引擎来解决,虽能保证强一致性但逻辑复杂,性能损失大。因此放弃了强一致性改为保证最终一致性,元数据状态机及文件状态机内都有定时器来检查不一致的状态。

1. 元数据存储-BlobMetaStateMachine

  开始时想设计为一个集群对应一个BlobMetaRaftGroup,后来考虑到单个RaftGroup可能会压力较大,所以改为每个Application对应一个BlobMetaRaftGroup。每个元数据状态机主要存储以下各项信息:

  • 目录元数据:包括目录名称及标识,该目录下分配了多少个Chunk,每个Chunk占用了多少空间,隶属于哪个RaftGroup等;
  • 文件元数据:包括文件名称及标识,该文件隶属的目录标识及隶属的ChunkRaftGroup标识等;
  • Chunk元数据: 包括Chunk的RaftGroup内的各个RaftNode分配在集群的哪个节点上;
  • 写锁数据:用于并发写时加锁。

  确认了需要存储哪些信息后,就需要确认如何将这些数据映射至底层的KV存储,既要保证高效又要方便Api检索这些元数据,经过一些尝试后最终定为以下方案。

目录元数据 Key

TypeFlag AppId 目录名称UTF8编码
8bit 8bit n bit
  • TypeFlag = 0
  • 注意:最后一个'/' 0x2F被替换为0x00,以方便扫描某一目录下所有子目录

目录元数据 Value

目录Id Chunk RaftGroup数量 Chunk RaftGroupIds
128bit 16bit n * 64bit

文件元数据 Key

TypeFlag AppId 目录Guid 分隔占位 名称UTF8编码
8bit 8bit 128bit 8bit n bit
  • TypeFlag = 1
  • 分隔占位始终 = 0

文件元数据 Value

文件Id 文件大小 Chunk RaftGroupId
128bit 32bit 64bit

2. 文件存储-BlobChunkStateMachine

  根据上述设计,每个目录下的文件分成了多个存储组(BlobChunkRaftGroup),本来想用MemoryMapFile来实现底层Chunk存储,但考虑到有更重要的功能要实现所以暂偷懒直接利用Linux文件系统来存储文件,状态机Apply文件写命令时,将文件直接写入节点运行时blob/ChunkRaftGroupId/目录下。

3. 读写流程

  • 读流程较简单: 发送读元数据命令至BlobMetaRaftGroup获取文件元数据(缓存),然后再分小块发读命令至目标ChunkRaftGroup获取文件小块数据;
  • 写流程要考虑元数据与文件数据的一致性,还要考虑在目录下无可用ChunkRaftGroup时创建新的组,具体参考以下设计草图:
    AppBoxFuture(五): 分布式文件存储-Store Everything

二. 实现效果

  根据以上设计在经历了1个月的编码后已初步实现(其中约一半时间在更改架构,抛弃了Mono依赖,改为Hosting CoreCLR,性能提升1倍),在框架IDE内每个Application内有个"BlobStore"节点,如下图所示可测试上传文件,然后通过浏览器访问上传至/pub目录内的文件(http://{地址:端口}/blob/{app名称}/{文件路径} eg: http://xx.xx.xx.xx:5000/blob/sys/imgs/aa.jpg
AppBoxFuture(五): 分布式文件存储-Store Everything

  作者简单测试了一下通过框架WebHost下载文件的性能(测试时尚未实现缓存元数据, 虚拟机I74C8G),如下图所示:
AppBoxFuture(五): 分布式文件存储-Store Everything

三. 本篇小结

  本实现适用于存储大量小文件,如业务单证的附件,或者用于OA系统作为文档库。目前只是实现了基本的上传下载功能,删除、重命名、Chunk合并等功能尚未实现,另待将来框架实现反向索引后再实现全文搜索功能。

  框架已更新,如何安装测试请参考AppBoxFuture(一): Hello Future!。如果您有问题或Bug报告,请留言或在Github提交Issue。

上一篇:大型分布式C++框架《一:框架简介》


下一篇:爬虫基础(五)-----scrapy框架简介