SeaweedFS文件系统
2018-04-19 本文已影响0人
DebugLiSir
0 SeaweedFS的使用方式
以存放文件为例来讲述目前使用方式跟官网的区别
![](https://img.haomeiwen.com/i11365866/f0bd820c32f15d1c.png)
![](https://img.haomeiwen.com/i11365866/18cae64469b97742.png)
采用这种方式的原因是:可以自己来设定文件的Key值,不要中间服务器来记录并转变文件到Key值之间的映射关系。
读取文件时,跟存放文件采用相同的方式。
- 官网给的方式仍是通过Master获取文件真正存放地址,然后再次访问获取文件内容。
- 目前使用的是直接访问Volume获取文件内容。如果从Master获取会出现301情况。
1 整个文件系统的UML图
![](https://img.haomeiwen.com/i11365866/bf0cbab31874abb7.png)
SeaweedFS文件管理主要分为两个部分:
- 对于文件实体的管理(Needle类)
- 对于索引文件的管理(根据储存方式分为InMemory、LevelDb、BoltDb、Btree)
对于文件实体的管理,都存放在.dat文件中。
对于索引文件的管理,目前项目采用的方式为InMemory。
对于三个类要特别注意一下:
Needle类(分为四部分Header、Body、CRC、Padding)
成员名 | 类型 | 所属部分 | 说明 |
---|---|---|---|
Cookie | uint32 | Header | 用于存放随机访问码,目前所有文件为0 |
Id | uint64 | Header | 文件的唯一性编号,目前使用方式为1z0x0y |
Size | uint32 | Header | 用于记录整个NeedleBody的大小 |
DataSize | uint32 | Body | 用于记录所要存储文件的大小,文件最大为4G |
Data | []byte | Body | 用于记录文件内容 |
Flags | byte | Body | 用于记录Body各种属性,例如gzip等 |
NameSize | uint8 | Body | 用于记录文件名称大小 |
Name | []byte | Body | 用于记录文件名称 |
MimeSize | uint8 | Body | 用于Mime的大小 |
Mime | []byte | Body | 用于记录上传时的文件头部内容,例如 Content-Type |
LastModified | uint64 | Body | 文件的最后修改时间,.dat文件只保留5个字节 |
Ttl | *TTL | Body | 文件有效期 |
PairsSize | uint16 | Body | 用于记录Pairs大小 |
Pairs | []byte | Body | 使用JSON格式来存放文件的其他信息 |
Checksum | CRC | CRC | 仅对Data进行crc32的校验 |
Padding | []byte | Padding | 保证每个Needle实体符合8字节对其规范 |
使用InMemory模式管理索引文件时,使用的NeedleValue类
成员名 | 类型 | 说明 |
---|---|---|
Key | uint64 | 文件的唯一性ID |
Offset | uint32 | 对应的文件实体Needle在.dat文件中的偏移量(按8字节对其方式计算),因此.dat文件的最大值为32G |
Size | uint32 | 存放的Needle中Body部分的大小 |
每个Volume使用的SuperBlock类,这个类用来记录卷的信息。
存在问题:
- 由于Offset大小为uint32,限制卷文件的大小。
成员名 | 类型 | 使用字节数 | 说明 |
---|---|---|---|
version | uint8 | 1 | 卷所使用的版本,目前都是2版本 |
ReplicaPlacement | *ReplicaPlacement | 1 | 卷的副本数量 |
Ttl | TTL | 2 | 卷的有效期 |
CompactRevision | uint16 | 2 | 卷被紧缩的次数 |
2 卷文件
SeaweedFS中每个卷分为两个文件:
- .dat文件,用于存放源文件内容(由Needle类构成)
- .idx文件,用于存放源文件的索引(由NeedleValue类构成)
.dat文件图示如下:
![](https://img.haomeiwen.com/i11365866/987c49fdbe9e406c.jpg)
.dat文件中前8个字节由SuperBlock类构成,后面的内容由Needle按照8字节对齐的方式进行拼装组成
.idx文件图示如下:
![](https://img.haomeiwen.com/i11365866/34144c0d17f5d64c.jpg)
.idx文件由NeedleValue类拼装组成。由offset字段来指出对应的Needle在.dat文件中的位置。
3 卷文件同步
对于卷同步,从两个角度来看待这个问题:
- 上传文件时,卷与卷之间的同步
- 新增机器时,机器之间卷的同步
对于第一点,SeaweedFS所采用处理方式如下:
- 询问Master,需要同步的卷所在位置(URL)
- 组装HTTPRequest,依次向需要同步的卷发送HTTP请求
问题:
- 这里就存在一个卷数据的一致性问题。如果需要同步的卷网络暂时出现问题,则消息无法进行同步。
- 上传速度较慢,每一个文件组成一个HTTP请求。对于大量的瓦片数据需要较长时间上传完成。目前3796640个瓦片数据(0-14级),需要4.5个小时左右才能上传完成。
对于第二点,SeaweedFS官网给出的处理方式如下:
复制对应的.dat和.idx文件到新机器上,从而使其卷数据一致。
问题:这种方式非常不利于系统的水平扩展。
4 目前服务器开发方向
最终目的:联合切片一起,做到从切片过程到发布过程的自动化处理。
目前面临的问题:
- 上传数据耗时过长。
- 卷数据一致性问题。
- 系统的水平扩展后数据同步的问题。
- 扩展到18级时,目前使用的Key值无法继续使用。
- 卷大小超过32G时产生的问题。
目前想到处理方式:
- 对于上传耗时过长的问题,准备采用直接产生卷文件的方式来解决。
- 卷数据一致性问题,准备采用改变volume的同步方式,使用raft协议保证数据一致性。
- 系统水平扩展,准备采用volume的一致性方案看是否能够解决。
- 扩展到18级瓦片的问题,准备改变key值的生成方式来完成。
- 卷大小超过32G时,采用将瓦片分在不同卷中,并且通过卷的collection来判断是否是同一批数据。
已经完成的测试工作:
- 已经完成从切片到生成大文件的联调工作,完成了生成大文件的C++代码。
- 分布式切片生成的大文件归并代码已经完成,并自测完成。
- 编写代码并测试本地机器卷与卷之间的同步,120W左右的文件大概需要9分钟左右同步完成。(此同步使用的是HTTP请求)
- 了解raft协议的工作原理,查看了goraft的代码。
- 上传时,采用多个文件一个HTTP请求发送。但速度提升较小,放弃这种方式。
整个工作流程图示如下:
![](https://img.haomeiwen.com/i11365866/61364c74448a35fe.png)