分布式文件存储:FastDFS简单使用与原理分析
引言
FastDFS属于分布式存储范畴,分布式文件系统FastDFS非常适合中小型项目,在我接手维护公司图片服务的时候开始接触到它,本篇文章目的是总结一下FastDFS的知识点。
用了2台2核4G的阿里云服务器做集群部署,具体部署步骤请参考:https://github.com/happyfish100/fastdfs/wiki
1、FastDFS分布式文件系统概述
FastDFS是一个轻量级的开源分布式文件系统,作者为淘宝资深架构余庆。
FastDFS主要解决了分布式文件存储与高并发访问的问题,实现了负载均衡,适合存储图片、视频、文档等文件,而且支持存储服务器的在线扩容。
2、FastDFS架构
FastDFS服务端有两个角色:Tracker与Storage,其中Tracker主要做调度工作,有着负载均衡作用,Storage负责文件存取、同步等操作。
FastDFS系统结构:
2.1、Client
客户端访问FastDFS分布式存储,一般为后端应用。
2.2、Tracker
Tracker在FastDFS集群中有两大作用:
- 管理Storage集群,在Storage服务启动时,会把自己注册到Tracker上,并定期上报自身状态信息,包括磁盘剩余空间、文件同步状态、文件上传下载次数等统计信息。
- Client访问Storage服务之前,必须先访问Tracker,动态获取到Storage服务的连接信息,有着负载均衡的作用。
2.3、Storage
Storage是数据存储服务器,文件和meta data都保存在Storage服务器中。
有以下特点:
- 采用高可用的方式进行数据存储。
- FastDFS集群中,Storage按组(Group/volume)提供服务,不同组的Storage之间不会互相通信,同组内的Storage之间会相互连接,进行文件同步。
- Storage服务采用binlog文件记录文件上传、删除等更新操作,binlog中只记录文件名,不记录内容。
- 文件同步只在同组内的Storage服务之间进行,采用push方式,即圆通服务器同步给目标服务器。
- FastDFS将文件及相关的描述信息(MetaData)保存在Storage服务中,文件存储以后将返回唯一的文件标识,文件标识有组名和文件名两部分构成,MetaData是文件的描述信息,如width=1024,height=768。
3、文件上传原理
文件上传的原理如下图:
- Client询问Tracker可以上传到哪个Storage。
- Tracker返回一台可用的Storage连接信息。
- Client直接与Storage通信,完成文件上传。
- Storage保存文件以后,返回Client文件标识(组名、文件名)。
4、文件下载原理
文件下载原理如下图:
- Client询问Tracker下文文件的Storage,参数为文件标识(组名、文件名)。
- Tracker返回一台可用的Storage。
- Client与Storage通信,完成文件下载过程。
5、文件同步原理
- 同一个组内的Storage服务是对等的,文件上传、删除等操作可以在任意一台Storage服务上执行,数据会在同组内Storage内同步。
- 文件同步(上传、删除、更新)采用push方式,即源服务器同步给目标服务器。
- 只有源头数据才需要同步,如果备份数据再次同步就会形成环路。
- 当新增Storage服务时,将已有的一台Storage的所有数据(源头数据与备份数据)同步给这台新增服务器。
6、服务端文件目录
6.1、TrackerServer
1 | ${base_path} |
6.2、StorageServer
1 | ${base_path} |
7、服务端与客户端通讯协议
7.1、 通讯协议介绍
FastDFS服务端与客户端通讯时候采用的是自定义的通讯协议,如下图所示:
协议包由两部分组成:header和body
- header共10字节,格式如下:
- 8 bytes body length
- 1 byte command
- 1 byte status
- body数据包格式取决于具体的命令,body可以为空。
7.2、命令代码和通讯状态代码
7.2.1、Tracker管理命令代码
名称 | 命令 |
---|---|
删除storage | 93 |
获取下载节点QUERY_FETCH_ONE | 102 |
获取更新节点QUERY_UPDATE | 103 |
不按组获取存储节点 | 101 |
按组获取存储节点 | 104 |
获取组列表 | 91 |
获取存储节点列表 | 92 |
7.2.2、 Store文件上传命令代码
名称 | 命令 | 说明 |
---|---|---|
文件上传 | 11 | 一般的文件上传,上传后为主文件 |
上传附属文件 | 21 | “上传从文件文件,比如主文件为xxx.jpg,从文件(缩略图)为xxx-150_150.jpg” |
删除文件 | 12 | 删除文件 |
设置文件元数据 | 13 | 上传文件创建日期,标签等 |
文件下载 | 14 | |
获取文件元数据 | 15 | |
查询文件信息 | 22 | 查询文件信息 |
创建支持断点续传的文件 | 23 | 创建一个支持断点续传的文件 |
断点续传 | 24 | 上传可断点上传的文件,如将大文件切为几份,分开上传 |
文件修改 | 34 | 修改支持断点上传的文件 |
清除文件 | 36 | 截取(清除)支持断点上传的文件 |
7.2.3、报文通讯状态代码
名称 | 代码 |
---|---|
客户端关闭连接命令 | 82 |
连接状态检查命令 | 111 |
服务端正确返回报文 | 100 |
8、简单使用
我使用的是fastdfs-client-java-1.27-SNAPSHOT.jar
happyfish100/fastdfs-client-java
这个库从17年6月5号之后就停止更新了,最近又开始更新代码了,看样子要维护了啊。
简单的对客户端进行了连接池的封装,方便使用。
- 系统启动,池子管理连接
- 心跳确认连接是否可靠
- 构造器模式创建连接池
- 回调方式使用客户端
源码地址:
以下为核心代码:
1.1、 初始化连接池
1 | /** |
1.2、 客户端执行请求
1 | /** |
1.3、 心跳
1 | /** |
1.4、 使用方式
1 | //初始化连接池 |
参考
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ClawHub的技术分享!