现在的位置: 首页 > 大数据 > 正文

FastDFS合并存储策略

2016年07月25日 大数据 ⁄ 共 2975字 ⁄ 字号 暂无评论

FastDFS提供了合并存储功能的实现,所有的配置都在tracker.conf文件之中,具体摘录如下:
trunk功能启动与配置:通过tracker.conf文件启动与配置,个配置项如下:
use_trunk_file = false#是否启用trunk存储
slot_min_size = 256#trunk文件最小分配单元
slot_max_size = 16MB#trunk内部存储的最大文件,超过该值会被独立存储
trunk_file_size = 64MB#trunk文件大小
trunk_create_file_advance = false#是否预先创建trunk文件
trunk_create_file_time_base = 02:00#预先创建trunk文件的基准时间
trunk_create_file_interval = 86400#预先创建trunk文件的时间间隔
trunk_create_file_space_threshold = 20G#trunk创建文件的最大空闲空间
trunk_init_check_occupying = false#启动时是否检查每个空闲空间列表项已经被使用
trunk_init_reload_from_binlog = false#是否纯粹从trunk-binlog重建空闲空间列表
trunk_compress_binlog_min_interval = 0#对trunk-binlog进行压缩的时间间隔

合并存储文件命名与文件结构
    我们知道向FastDFS上传文件成功时,服务器返回该文件的存取ID叫做file_id,当没有启动合并存储时该file_id和磁盘上实际存储的文件一一对应,当采用合并存储时就不再一一对应而是多个file_id对应的文件被存储成一个大文件。
注:下面将采用合并存储后的大文件统称为Trunk文件,没有合并存储的文件统称为源文件;
区分三个概念:
    1)Trunk文件:storage服务器磁盘上存储的实际文件,默认大小为64MB
    2)合并存储文件的file_id:表示服务器启用合并存储后,每次上传返回给客户端的file_id,注意此时该file_id与磁盘上的文件没有一一对应关系;
    3)没有合并存储的file_id:表示服务器未启用合并存储时,Upload时返回的file_id
    Trunk文件文件名格式:fdfs_storage1/data/00/00/000001 文件名从1开始递增,类型为int;

1、在启动合并存储时服务返回给客户端的file_id也会有所变化

具体如下:

1) 没有合并存储时file_id:group1/M00/00/00/CmQPRlP0T4-AA9_ECDsoXi21HR0.tar.gzCmQPRlP0T4-AA9_ECDsoXi21HR0.tar.gz
这个文件名中,除了.tar.gz 为文件后缀,CmQPRlP0T4-AA9_ECDsoXi21HR0 这部分是一个base64编码缓冲区,组成如下:
storage_id(ip的数值型)
timestamp(创建时间)
file_size(若原始值为32位则前面加入一个随机值填充,最终为64位)
crc32(文件内容的检验码)

2)合并存储时file_id:group1/M00/00/00/CgAEbFQWWbyIPCu1AAAFr1bq36EAAAAAQAAAAAAAAXH82.conf
采用合并的文件ID更长,因为其中需要加入保存的大文件id以及偏移量,具体包括了如下信息:
file_size:占用大文件的空间(注意按照最小slot-256字节进行对齐)
mtime:文件修改时间
crc32:文件内容的crc32码
formatted_ext_name:文件扩展名
alloc_size:文件大小与size相等
id:大文件ID如000001
offset:文件内容在trunk文件中的偏移量
size:文件大小

2、Trunk文件内部结构
    trunk内部是由多个小文件组成,每个小文件都会有一个trunkHeader(可认为是元数据),以及紧跟在其后的真实数据,结构如下:
|||——————————————————— 24bytes——————-—————————|||
|—1byte   —|—4bytes    —|—4bytes —|—4bytes—|—4bytes —|—7bytes                      —|
|—filetype—|—alloc_size—|—filesize—|—crc32  —|—mtime —|—formatted_ext_name—|
|||——————file_data filesize bytes——————————————————————|||
|———————file_data————————————————————————————|
    每个Trunk-Header从上图可以看到,占用了72字节。

合并存储空闲空间管理
1、概述
    Trunk文件为64MB(默认),因此每次创建一次Trunk文件总是会产生空余空间,比如为存储一个10MB文件,创建一个Trunk文件,那么就会剩下接近54MB的空间(TrunkHeader 会24字节,后面为了方便叙述暂时忽略其所占空间),下次要想再次存储10MB文件时就不需要创建新的文件,存储在已经创建的Trunk文件中即可。另外当删除一个存储的文件时,也会产生空余空间。
    在Storage内部会为每个store_path构造一颗以空闲块大小作为关键字的空闲平衡树,相同大小的空闲块保存在链表之中。每当需要存储一个文件时会首先到空闲平衡树中查找大于并且最接近的空闲块,然后试着从该空闲块中分割出多余的部分作为一个新的空闲块,加入到空闲平衡树中。例如:要求存储文件为300KB,通过空闲平衡树找到一个350KB的空闲块,那么就会将350KB的空闲块分裂成两块,前面300KB返回用于存储,后面50KB则继续放置到空闲平衡树之中。
    假若此时找不到可满足的空闲块,那么就会创建一个新的trunk文件64MB,将其加入到空闲平衡树之中,再次执行上面的查找操作(此时总是能够满足了)。

2、TrunkServer
    假若所有的Storage都具有分配空闲空间的能力(upload文件时自主决定存储到哪个TrunkFile之中),那么可能会由于同步延迟导致数据冲突,例如:Storage-A:Upload一个文件A.txt 100KB,将其保存到000001这个TrunkFile的开头,与此同时,Storage-B也接受Upload一个文件B.txt 200KB,将其保存在000001这个TrunkFile文件的开头,当Storage-B收到Storage-A的同步信息时,他无法将A.txt
保存在000001这个trunk文件的开头,因此这个位置已经被B.txt占用。

   为了处理这种冲突,引入了TrunkServer概念,只有TrunkServer才有权限分配空闲空间,决定文件应该保存到哪个TrunkFile的什么位置。TrunkServer由Tracker指定,并且在心跳信息中通知所有的Storage。
    引入TrunkServer之后,一次Upload请求,Storage的处理流程图如下: 

给我留言

您必须 [ 登录 ] 才能发表留言!