fastdfs 合并存储trunk

我们两清 提交于 2019-12-02 05:55:21

一、关于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配置是否生效

  1. 通过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个字节

  1. trunk file id
  2. 文件在trunk file内部的offset
  3. 文件占用的存储空间大小,字节对齐及删除空间复用,文件占用存储空间>=文件大小

每个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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!