分布式文件存储: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
${base_path}
|__data
| |__storage_groups.dat:存储分组信息
| |__storage_servers.dat:存储服务器列表
|__logs
|__trackerd.log:tracker server日志文件
6.2、StorageServer
${base_path}
|__data
| |__.data_init_flag:当前storage server 初始化信息
| |__storage_stat.dat:当前storage server统计信息
| |__sync:存放数据同步相关文件
| | |__binlog.index:当前的binlog文件索引号
| | |__binlog.###:存放更新操作记录(日志)
| | |__${ip_addr}_${port}.mark:存放同步的完成情况
| |
| |__一级目录:256个存放数据文件的目录,如:00, 1F
| |__二级目录:256个存放数据文件的目录
|__logs
|__storaged.log:storage server日志文件
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、 初始化连接池
/**
* Build fast dfs conn pool.
*
* @return the fast dfs conn pool
*/
public FastDFSConnPool build() {
// 初始化空闲连接池
idleConnectionPool = new LinkedBlockingQueue<>(maxPoolSize);
//初始化全局参数
try {
ClientGlobal.init(confFileName);
} catch (IOException | MyException e) {
throw new RuntimeException("init client global exception.", e);
}
// 往线程池中添加默认大小的线程
TrackerServer trackerServer;
for (int i = 0; i < minPoolSize; i++) {
//获取到连接
trackerServer = createTrackerServer();
if (trackerServer != null) {
//放入空闲池
idleConnectionPool.offer(trackerServer);
}
}
// 注册心跳
new HeartBeat(this).beat();
return this;
}
1.2、 客户端执行请求
/**
* 执行方式
*
* @param <T> the type parameter
* @param invoke the invoke
* @return the t
*/
public <T> T processFdfs(CallBack<T> invoke) {
TrackerServer trackerServer = null;
T t;
try {
//获取tracker连接
trackerServer = fastDFSConnPool.checkOut();
//获取storage
StorageClient1 storageClient = new StorageClient1(trackerServer, null);
//执行操作
t = invoke.invoke(storageClient);
//释放连接
fastDFSConnPool.checkIn(trackerServer);
return t;
} catch (Exception e) {
//删除链接
fastDFSConnPool.drop(trackerServer);
throw new RuntimeException(e);
}
}
1.3、 心跳
/**
* 心跳任务
*/
private class HeartBeatTask implements Runnable {
@Override
public void run() {
LinkedBlockingQueue<TrackerServer> idleConnectionPool = fastDFSConnPool.getIdleConnectionPool();
TrackerServer ts = null;
for (int i = 0; i < idleConnectionPool.size(); i++) {
try {
ts = idleConnectionPool.poll(fastDFSConnPool.getWaitTimes(), TimeUnit.SECONDS);
if (ts != null) {
ProtoCommon.activeTest(ts.getSocket());
idleConnectionPool.add(ts);
} else {
//代表已经没有空闲长连接
break;
}
} catch (Exception e) {
//发生异常,要删除,进行重建
logger.error("heart beat conn have dead, and reconnect.", e);
fastDFSConnPool.drop(ts);
}
}
}
}
1.4、 使用方式
//初始化连接池
FastDFSConnPool fastDFSConnPool = new FastDFSConnPool()
.confFileName("./config/fdfs_client.conf")
.maxPoolSize(8)
.minPoolSize(1)
.reConnNum(2)
.waitTimes(2).build();
//使用客户端
FastDFSClient client = new FastDFSClient(fastDFSConnPool);
//上传 ileName 文件全路径 extName 文件扩展名,不包含(.) metas 文件扩展信息
String parts = client.processFdfs(storageClient -> storageClient.upload_file1("fileName", "extName", new NameValuePair[0]));
//下载 fileId: group1/M00/00/00/wKgRsVjtwpSAXGwkAAAweEAzRjw471.jpg
byte[] bytes = client.processFdfs(storageClient -> storageClient.download_file1("fileId"));
//删除 -1失败,0成功
int result = client.processFdfs(storageClient -> storageClient.delete_file1("fileId"));
//获取远程服务器文件资源信息 groupName 文件组名 如:group1 remoteFileName M00/00/00/wKgRsVjtwpSAXGwkAAAweEAzRjw471.jpg
FileInfo fileInfo = client.processFdfs(storageClient -> storageClient.get_file_info("groupName", "remoteFileName"));
参考

分布式文件存储:FastDFS简单使用与原理分析的更多相关文章
- 分布式文件存储FastDFS(一)初识FastDFS
一.FastDFS简单介绍 FastDFS是一款开源的.分布式文件系统(Distributed File System),由淘宝开发平台部资深架构师余庆开发.作为一个分布式文件系统,它对文件进行管理. ...
- (转) 分布式文件存储FastDFS(一)初识FastDFS
http://blog.csdn.net/xingjiarong/article/details/50559849 一.FastDFS简介 FastDFS是一款开源的.分布式文件系统(Distribu ...
- Centos7部署分布式文件存储(Fastdfs)
目录 FastDFS介绍 楼主目标:前可H5撩妹,后可Linux搞运维 环境:Centos7 软件: 软件链接: 安装前所有准备,上传软件到Centos7上的/opt的目录下 安装依赖软件和类库(安装 ...
- 分布式文件存储FastDFS(七)FastDFS配置文件具体解释
配置FastDFS时.改动配置文件是非常重要的一个步骤,理解配置文件里每一项的意义更加重要,所以我參考了大神的帖子,整理了配置文件的解释.原帖例如以下:http://bbs.chinaunix.net ...
- (转) 分布式文件存储FastDFS(七)FastDFS配置文件详解
http://blog.csdn.net/xingjiarong/article/details/50752586 配置FastDFS时,修改配置文件是很重要的一个步骤,理解配置文件中每一项的意义更加 ...
- (转)分布式文件存储FastDFS(四)配置fastdfs-apache-module
http://blog.csdn.net/xingjiarong/article/details/50560605 在前边我们已经配置好了FastDFS的环境,但是此时的FastDFS还不能通过htt ...
- (转)分布式文件存储FastDFS(三)FastDFS配置
http://blog.csdn.net/xingjiarong/article/details/50559768 在上一节中我们一起搭建了一个单节点的FastDFS系统,但是仅仅将系统搭建起来是远远 ...
- (转)分布式文件存储FastDFS(二)FastDFS安装
http://blog.csdn.net/xingjiarong/article/details/50559761 在前面的一篇中,我们分析了FastDFS的架构,知道了FastDFS是由客户端,跟踪 ...
- (转)分布式文件存储FastDFS(六)FastDFS多节点配置
http://blog.csdn.net/xingjiarong/article/details/50759918 前面几篇关于FastDFS的博客中介绍了如何在一台机器上搭建一个简易的FastDFS ...
随机推荐
- 借助GPU Boost和K80 Autoboost提高性能
原网站:https://devblogs.nvidia.com/increase-performance-gpu-boost-k80-autoboost/ 由于我主要使用nvidia-smi,故nvc ...
- cxuan读者的外包面试之旅
最开始是打算面试外包公司刷经验,等经验差不多了,再去甲方尝试,可惜不太顺利. 一.迈思(面试了30分钟) 自我介绍 左连接(a 表左连接 b 表,a 表全部数据出来,b 表没有的数据为空) a 表左连 ...
- 牛逼了,利用Python实现“天眼系统”,只要照片就能了解个人信息
- 11、Composite 组合模式 容器与内容的一致性(抽象化) 结构型设计模式
1.Composite模式定义 组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这 ...
- java 序列化流与反序列化流
一 对象序列化流ObjectOutputStream ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream.可以使用 ObjectInputStr ...
- Vue 引入指定目录文件夹所有的组件 require.context
require.context require.context是webpack中用来管理依赖的一个函数,此方法会生成一个上下文模块,包含目录下所有的模块的引用,同构正则表达式匹配,然后require进 ...
- hadoop2.6虚拟机安装
Linux环境设置/*安装Hadoop集群时要确保以下几个方面1.本机与虚拟机之间是否可以通信(Ping).如果不行检查下面 1.1本机防火墙关闭(开启情况是本机可以ping虚拟机,虚拟机不能ping ...
- nohup 命令的使用
nohup 命令的使用 1. nohup简介 nohup 命令运行由 Command参数和任何相关的 Arg参数指定的命令,忽略所有挂断(SIGHUP)信号.在注销后使用 nohup 命令运行后台中的 ...
- pytest封神之路第一步 tep介绍
『 tep is a testing tool to help you write pytest more easily. Try Easy Pytest! 』 tep前身 tep的前身是接口自动化测 ...
- 编译原理根据项目集规范族构造LR(0)分析表
转载于https://blog.csdn.net/Johan_Joe_King/article/details/79058597?utm_medium=distribute.pc_relevant.n ...