乐趣区

关于fastdfs:FastDFS-海量小文件存储解决之道

作者:vivo 互联网服务器团队 -Zhou Changqing

一、FastDFS 原理介绍

FastDFS 是一个 C 语言实现的开源轻量级分布式文件系统。

反对 Linux、FreeBSD、AID 等 Unix 零碎,解决了大容量的文件存储和高并发拜访问题,文件存取实现了负载平衡,适宜存储 4KB~500MB 之间的小文件,特地适宜以文件为载体的在线服务,如图片、视频、文档等等。

二、FastDFS 架构

FastDFS 由三个局部形成:

  • 客户端(Client)
  • 跟踪服务器(TrackerServer)
  • 存储服务器(StorageServer)

2.1 Tracker Server (跟踪服务器)

Tracker Server (跟踪服务器) 次要是做调度工作,起到负载平衡的作用。

(1)【服务注册】治理 StorageServer 存储集群,StorageServer 启动时,会把本人注册到 TrackerServer 上,并且定期报告本身状态信息,包含磁盘残余空间、文件同步情况、文件上传下载次数等统计信息。

(2)【服务发现】Client 拜访 StorageServer 之前,必须先拜访 TrackerServer,动静获取到 StorageServer 的连贯信息,最终数据是和一个可用的 StorageServer 进行传输。

(3)【负载平衡】

  • store group 调配策略:
  • 0:轮询形式
  • 1:指定组
  • 2:均衡负载 (抉择最大残余空间的组(卷) 上传)
  • store server 调配策略:
  • 0:轮询形式
  • 1:依据 IP 地址进行排序抉择第一个服务器(IP 地址最小者)
  • 2:依据优先级进行排序(上传优先级由 storage server 来设置,参数名为 upload_priority)
  • stroe path 调配:
  • 0:轮流形式,多个目录顺次寄存文件
  • 2:抉择残余空间最大的目录寄存文件(留神:残余磁盘空间是动静的,因而存储到的目录或磁盘可能也是变动的)

2.2 Tracker Server (跟踪服务器)

Tracker Server (跟踪服务器) 次要提供容量和备份服务。

【分组治理】以 Group 为单位,每个 Group 蕴含多台 Storage Server,数据互为备份,存储容量以 Group 内容量最小的 storage 为准,已 Group 为单位组织存储不便利用隔离、负载平衡和正本数据定制。

毛病:Group 容量受单机存储容量的限度,数据恢复只能依赖 Group 其余机器从新同步。

【数据同步】文件同步只能在 Group 内的 Storage Server 之间进行,采纳 push 形式,即源服务器同步给指标服务器。源服务器读取 binlog 文件,将文件内容解析后,按操作命令发送给指标服务器,有指标服务按命令进行操作。

三、上传下载流程

3.1 上传流程解析

3.1.1 抉择 Tracker Server

集群中的 tracker 之间都是对等的,客户端在上传文件时可任意抉择一个 tracker 即可。

3.1.2 调配 Group、Stroage Server 和 storage path(磁盘或者挂载点)

tracker 接管到上传申请时会先给该文件调配一个能够存储的 Group,而后在 Group 中调配一个 Storage Server 给客户端,最初在接管到客户端写文件申请时,Storage Server 会调配一个数据存储目录并写入。

(该过程中的调配策略详见:【负载平衡】)

3.1.3 生成 file_id 写入并返回

Storage 会生成一个 file\_id 来作为以后文件名,file\_id 采纳 base64 编码,蕴含:源 storage server ip、文件创建工夫、文件大小、文件 CRC32 校验码 和 随机数。每个存储目录下 有两个 256*256 个子目录。

Storage 会依据 file_id 进行两次 hash 路由到其中一个子目录中。

最初以 file_id 为文件名存储文件到该子目录下并返回文件门路给客户端。

最终文件存储门路:

分组 | 磁盘 | 子目录 | 文件名

group1/M00/00/89/eQ6h3FKJf_PRl8p4AUz4wO8tqaA688.apk

  • 【分组】:文件上传时调配 Group。
  • 【磁盘门路】:存储服务器配置的虚构门路,对应配置参数 store\_path 例如:M00 对应 store\_path0,M01 对应 store_path1。
  • 【两级目录】:存储服务器在每个虚构磁盘门路下创立的两级目录,用于存储文件。

3.2  下载流程解析

3.2.1 解析门路并路由

tracker 接管 client 发送的下载申请时,tracker 从文件名中解析出 Group、大小、创立工夫等信息,而后依据 Group 抉择一个 storage server 返回。

3.2.2 校验读取并返回

客户端和 Storage Server 建设链接,校验文件是否存在,最终返回文件数据。

毛病:Group 之间文件同步是异步进行的,可能上传的文件还未同步到以后拜访的 Storage Server 这台机器上或者提早起因,将导致下载文件呈现 404。所以引入 nginx\_fastdfs\_module 能够很好的解决同步和提早问题。

3.3 引入 fastdfs\_nginx\_module 组件后的下载架构

FastDFS Nginx Module 性能介绍

(1)【防盗链查看】

利用 FastDFS nginx 扩大性能动静生成 token,设置 http.conf 配置。

  • 开启防盗链性能
  • http.default\_content\_type =
  • application/octet-stream
  • http.mime\_types\_filename=mime.types
  • 开启 token 防盗链性能
  • http.anti\_steal.check\_token=true
  • token 过期工夫
  • http.anti\_steal.token\_ttl=900
  • 密钥
  • http.anti\_steal.secret\_key=xxx
  • token 过期后返回的内容
  • http.anti\_steal.token\_check_fail=/etc/fdfs/anti-steal.jpg

【token 生成算法】:md5(fileid\_without\_group + privKey + ts) 同时 ts 没有超过 ttl 范畴。

服务器会主动依据 token,st 以及设置的秘钥来验证合法性。拜访链接模式如:

http://localhost/G1/M00/00/01/wKgBD01c15nvKU1cAABAOeCdFS466570.jpg?token=b32cd06a53dea4376e43d71cc882f9cb&ts=1297930137

(2)【文件元数据解析】

依据 file_id 获取元数据信息, 包含:源 storage ip,文件门路,名称,大小 等。

(3)【文件拜访路由】

因文件的 file_Id 蕴含了上传文件时的源 Storage Server IP,所以在获取不到本机下的文件时(未同步或者提早状况下)FastDFS 扩大组件,会依据源服务器 IP 来重定向或者代理形式获取文件。

  • 重定向模式

配置项 response_mode = redirect,服务器返回 302,重定向 url

http:// 源 storage ip:port/ 文件门路?redirect=1

  • 代理模式

配置项 response_mode = proxy,应用源 storage 地址作为代理 proxy 的 host,其余局部不变

四、同步机制

4.1 同步规定

同步只产生在本组的 Storage Server 之间。

源头数据才须要同步,备份数据不须要再次同步。

新增 Storage Server 时,会由已有一台 Storage Server 将已有的所有数据(源头数据和备份数据)同步给新增服务器。

4.2 Binlog 复制

FastDFS 文件同步采纳 binlog 异步复制形式,Storage Server 应用 binlog 文件记录文件上传、删除等操作,依据 Binlog 进行文件同步。Binlog 中只记录文件 ID 和操作,不记录文件内容 .binlog 格局如下:

工夫戳 | 操作类型 | 文件名

1490251373 C M02/52/CB/CtAqWVjTbm2AIqTkAAACd_nIZ7M797.jpg

操作类型(局部):

  • C 示意源创立、c 示意正本创立
  • A 示意源追加、a 示意正本追加
  • D 示意源删除、d 示意正本删除
  • . . . . . . .

4.3 同步流程

新增 Storage Server 后,组内其余 Storage Server 服务器会启动同步线程,在 tracker 的协调下向新增服务器发动全量和增量同步操作。

(1)Storage C 启动后向 tracker 上报所属 group、ip、port、版本号、存储目录数、子目录数、启动工夫、老数据是否同步实现,以后状态等信息。

(2)tracker 收到 Storage C 退出申请申请后,更新本地 storage list,返回给 C,并适时同步给 A、B。

(3)storage C 向 tracker 申请同步申请,响应后变更本身状态为 WAIT_SYNC。

(4)storage A 和 B 在心跳周期内从同步到的新 storage list 发现没有 C,则启动同步线程,先向 tracker 发动同步申请(TRACKER\_PROTO\_CMD\_STORAGE\_SYNC\_SRC\_REQ),tracker 会把同步源 IP 级同步工夫戳返回给 A 和 B, 如果源 IP 和本人本地 IP 统一,则标记本人作为同步源用来做老数据同步(全量同步源),如果不统一,则标记本人作为增量同步源(只有在 C 节点状态为 Active 时才同步)。该决策是由 tracker 抉择产生的,不可 A、B 同时作为同步源,同时同步给 C。

(5)同步源(假如是 storage A)以 .mark 为后缀的文件记录指标机器同步信息,并上报变更 storage C 状态为 SYNCING。

(6)从 /data.sync 目录下读取 binlog.index 中的,binlog 文件 Id,binlog.000 读取逐行读取,进行解析.(详见下面 binlog 内格局) 发送数据给 storage C,C 接管并保留。

(7)数据同步过程中 storage C 的状态变更过程 OFFLINE->ONLINE->ACTIVE。ACTIVE 是最终状态,示意 storage C 已对外提供服务。

五、文件存储

5.1 LOSF 问题

小文件存储(LOSF)面临的问题:

  • 本地文件系统 innode 梳理优先,存储小文件数量受限。
  • 目录层级和目录中文件数量会导致拜访文件开销很大(IO 次数多)。
  • 小文件存储,备份和复原效率低。

针对小文件存储问题,FastDFS 提供了文件合并解决方案。FastDFS 默认创立大文件为 64M,大文件能够存储很多小文件,包容一个小文件的空间叫 slot,solt 最小 256 字节,最大 16M。小于 256 字节当 256 字节存储,超过 16M 文件独自存储。

5.2 存储形式

(1)【默认存储形式】未开启合并,FastDFS 生成的 file_id 和磁盘上理论存储的文件一一对应。

(2)【合并存储形式】多个 file\_id 对应文件被存储成了一个大文件。trunk 文件名格局:/fastdfs/data/00/000001 文件名从 1 开始递增。而生成的 file\_id 更长,会新增 16 个字节额定内容用来保留偏移量等信息。

如下:

  • 【file_size】:占用大文件的空间(留神依照最小 slot-256 字节进行对齐)
  • 【mtime】:文件批改工夫
  • 【crc32】:文件内容的 crc32 码
  • 【formatted\_ext\_name】:文件扩展名
  • 【alloc_size】:文件大小与 size 相等
  • 【id】:大文件 ID 如 000001
  • 【offset】:文件内容在 trunk 文件中的偏移量
  • 【size】:文件大小。

5.3 存储空间治理

(1)【Trunk Server】由 tracker leader 在一组 Storage Server 抉择进去的,并告诉给该组内所有 Storage Server,负责为该组内所有 upload 操作调配空间。

(2)【闲暇均衡树】trunk server 会为每个 store_path 结构一个闲暇均衡树,雷同大小的闲暇块保留在链表中,每次上传申请时会到依据上传的文件大小到均衡树中查找获取大于或者靠近的闲暇块,而后从闲暇块中宰割出多余的作为新的闲暇块,重新加入均衡树。如果找不到则会重建一个新的 trunk 文件,并退出到均衡树中。该调配过程即是一个保护闲暇均衡树的过程。

(3)【Trunk Binlog】开启了合并存储后,Trunk Server 会多出一个 TrunkBinlog 同步。TrunkBinlog 记录了 TrunkServer 所有调配与回收的闲暇块操作,并由 Trunk Server 同步给同组中其余 storage server。

TrunkBinlog 格局如下:

工夫戳 | 操作类型 | store\_path\_index | sub\_path\_high| sub\_path\_low | file.id| offset | size 1410750754 A 0 0 0 1 0 67108864

各字段含意如下:

  • 【file.id】:TrunkFile 文件名,比方 000001
  • 【offset】:在 TrunkFile 文件中的偏移量
  • 【size】:占用的大小,依照 slot 对齐

六、文件去重

FastDFS 不具备文件去重能力,必须引入 FastDHT 来配合实现。FastDHT 是一个键值对的高效分布式 hash 零碎,底层采纳 Berkeley DB 来做数据库长久化,同步形式应用 binlog 复制形式。在 FastDFS 去重场景中,对文件内容做 hash,而后判断文件是否统一。

在文件上传胜利后,查看 Storage 存储对应存储门路,会发现返回的是一个软链接,之后每次反复上传都是返回一个指向第一次上传的文件的软链接。也就保障了文件只保留了一份。

(留神:FastDFS 不会返回原始文件的索引,返回的全部都是软链接,当所有的软链接都被删除的时候,原始文件也会从 FastDFS 中被删除)。

七、总结

FastDFS 真正意义上只是一个管理文件的零碎(利用级文件系统),比方治理上传文件、图片等。并不像零碎磁盘文件系统 NTFS 或者 FAT 等这种零碎级文件系统。

退出移动版