文章目录
一、关于fastdfs 合并存储
• 合并存储是指将多个小文件存储到一个较大的文件(trunk file)中,这个trunk file的文件大小是固定的,比如64MB。
• 小于一定size的文件才合并存储到trunk file中,否则在文件系统创建一个独立的文件来存储
• 海量小文件带来的挑战:
—文件系统inode面临不够的风险
—文件系统定位文件的效率急剧下降
• 合并存储可以有效地解决上面的两个问题,解决海量小文件的存储和访问问题。
• 小文件合并存储是业界普遍采用的做法。
二、fastdfs 合并存储trunk配置
配置参数都在tracker.conf里
•所有参数均在tracker.conf中配置,storage server启动的时候,从tracker server上获取
•修改了合并存储相关参数后,需要先重启tracker server,然后再重启storage server
主要关注配置参数:
#默认false 这里改成true
use_trunk_file = true
#trunk文件最小分配单元 默认就是256KB
slot_min_size = 256
#trunk内部存储的最大文件,超过该值会被独立存储
slot_max_size = 16MB
#trunk文件大小
trunk_file_size = 64MB
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进行压缩的时间间隔
合并存储的文件会在data/00/00/ 下从000001 文件开始,合并存储的文件不会产生新的文件,所以根据返回的文件ID,在存储目录下是找不到对应的文件的。合并存储并不影响fastdht排重效果。
1. 如何判断trunk配置是否生效
- 通过fieldid长短判断
上传文件,查看返回的fileid长度。
trunk模式返回的fileid比非truak模式的要长,因此要存储大文件id以及偏移量。
三、fastdfs 文件合并存储实现原理
FastDFS合并存储原理分析
参考URL: https://blog.csdn.net/hfty290/article/details/42026215
1. 基础
FastDFS提供的合并存储功能,默认创建的大文件为64MB,然后在该大文件中存储很多小文件。大文件中容纳一个小文件的空间称为一个Slot,规定Slot最小值为256字节,最大为16MB,也就是小于256字节的文件也需要占用256字节,超过16MB的文件不会合并存储而是创建独立的文件。
向FastDFS上传文件成功时,服务器返回该文件的存取ID叫做fileid,当没有启动合并存储时该fileid和磁盘上实际存储的文件一一对应,当采用合并存储时就不再一一对应而是多个fileid对应的文件被存储成一个大文件。
注:下面将采用合并存储后的大文件统称为Trunk文件,没有合并存储的文件统称为源文件;
请大家注意区分三个概念:
1)Trunk文件:storage服务器磁盘上存储的实际文件,默认大小为64MB
2)合并存储文件的FileId:表示服务器启用合并存储后,每次上传返回给客户端的FileId,注意此时该FileId与磁盘上的文件没有一一对应关系;
3)没有合并存储的FileId:表示服务器未启用合并存储时,Upload时返回的FileID
Trunk文件文件名格式:fdfs_storage1/data/00/00/000001 文件名从1开始递增,类型为int;
- 没有合并存储时fileid:
group1/M00/00/00/Cwxz112utW6AZNxCAAAABEd3frE136.txt
这个文件名中,除了.txt为文件后缀,Cwxz112utW6AZNxCAAAABEd3frE136 这部分是一个base64编码缓冲区,组成如下:
storage_id(ip的数值型)
timestamp(创建时间)
file_size(若原始值为32位则前面加入一个随机值填充,最终为64位)
crc32(文件内容的检验码)
- 合并存储时fileid
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:文件大小
FastDFS在V3.0版本里引入小文件合并存储的机制,可将多个小文件存储到一个大的文件(trunk file),为了支持这个机制,FastDFS生成的文件fileid需要额外增加16个字节
- trunk file id
- 文件在trunk file内部的offset
- 文件占用的存储空间大小,字节对齐及删除空间复用,文件占用存储空间>=文件大小
每个trunk file由一个id唯一标识,trunk file由group内的trunk server负责创建(trunk server是tracker选出来的),并同步到group内其他的storage,文件存储合并存储到trunk file后,根据其offset就能从trunk file读取到文件。
文件在trunk file内的offset编码到文件名,决定了其在trunk file内的位置是不能更改的,也就不能通过compact的方式回收trunk file内删除文件的空间。但当trunk file内有文件删除时,其删除的空间是可以被复用的,比如一个100KB的文件被删除,接下来存储一个99KB的文件就可以直接复用这片删除的存储空间。
2. Trunk文件内部结构
trunk内部是由多个小文件组成,每个小文件都会有一个trunkHeader,以及紧跟在其后的真实数据,结构如下:alloc_size : 文件大小与size等
filesize:该小文件占用大文件的空间,最小256KB 最大16M
crc32:文件内容的crc32码
mtime:文件的修改时间
formatted_ext_name:文件扩展名
可以看出TrunkHeader 部分占24字节。
3. trunk相关数据结构
trunk相关数据结构 定义在trunk_shared.h文件中,如下
整体以下两个结构组成,
FDFSTrunkHeader
FDFSTrunkFullInfo
其中FDFSTrunkFullInfo又包含2个结构FDFSTrunkPathInfo、FDFSTrunkFileInfo一个是trunk文件路径信息、一个trunk文件信息。
typedef struct tagFDFSTrunkHeader {
char file_type;
char formatted_ext_name[FDFS_FILE_EXT_NAME_MAX_LEN + 2];
int alloc_size;
int file_size;
int crc32;
int mtime;
} FDFSTrunkHeader;
typedef struct tagFDFSTrunkPathInfo {
unsigned char store_path_index; //store which path as Mxx
unsigned char sub_path_high; //high sub dir index, front part of HH/HH
unsigned char sub_path_low; //low sub dir index, tail part of HH/HH
} FDFSTrunkPathInfo;
typedef struct tagFDFSTrunkFileInfo {
int id; //trunk file id
int offset; //file offset
int size; //space size
} FDFSTrunkFileInfo;
typedef struct tagFDFSTrunkFullInfo {
char status; //normal or hold
FDFSTrunkPathInfo path;
FDFSTrunkFileInfo file;
} FDFSTrunkFullInfo;
4. 源码学习
下载如何判断是否是trunk文件
如下利用IS_TRUNK_FILE_BY_ID判断,核心是FDFSTrunkFileInfo结构中int id; //trunk file id字段的值是否大于0。
相关核心code
FDFSTrunkFullInfo trunkInfo;
IS_TRUNK_FILE_BY_ID(trunkInfo)
#define IS_TRUNK_FILE_BY_ID(trunkInfo) (trunkInfo.file.id > 0)
总结: trunkInfo 成员变量的填充,是根据客户端请求的fielid请求解析出来的。当trunk模式下,trunkInfo.file.id填充trunk file id。
四、FastDFS trunk 模式上传下载处理流程
1. 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。
五、参考
FastDFS深度学习
参考URL: https://www.cnblogs.com/msi-chen/p/10515356.html
FastDFS之合并存储缺陷导致数据丢失或错误
参考URL: https://www.it610.com/article/5631254.htm
来源:https://blog.csdn.net/inthat/article/details/102684390