分布式文件存储: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 ...
随机推荐
- 实验06——java自动封箱、自动拆箱
package cn.tedu.demo; /** * @author 赵瑞鑫 E-mail:1922250303@qq.com * @version 1.0 * @创建时间:2020年7月17日 上 ...
- Python 实现 T00ls 自动签到脚本(邮件+钉钉通知)
T00ls 每日签到是可以获取 TuBi 的,由于常常忘记签到,导致损失了很多 TuBi .于是在 T00ls 论坛搜索了一下,发现有不少大佬都写了自己的签到脚本,签到功能实现.定时任务执行以及签到提 ...
- 2020年最新的过某宝滑块验证技术,Python大牛轻松搞定技术难题
致谢: Charles未晞 Charles的皮卡丘 提供解决思路,此文实为借鉴. 前言: 利用selenium模拟登录淘宝,外界传言这个确实很难过,有各种轨迹检测. 但是我没想到淘宝的滑块验证码这么容 ...
- 如何利用Python在网上接单,兼职也能月薪过万
- JavaScript 模块封装
JavaScript 模块封装 前言介绍 在最早的时候JavaScript这门语言其实是并没有模块这一概念,但是随着时间的推移与技术的发展将一些复用性较强的代码封装成模块变成了必要的趋势. 在这篇文章 ...
- 2020-06-15:Redis分布式锁怎么解锁?
福哥答案2020-06-15: 答案来自群成员:1.setnx:del2.set:lua+del3.redisson:@Overridepublic void unlock(String lockKe ...
- Vercel托管博客
背景 本站已托管至Vercel,但作为一名前端小白,昨天帮朋友托管博客到Vercel的过程中到处碰壁,就想写一篇博客记录一下. 注册登录 点击Vercel官网{% btn 'https://verce ...
- storcli 命令(更新Ing)
help [root@centos7]# storcli -h Storage Command Line Tool Ver 007.0606.0000.0000 Mar , (c)Copyright ...
- 【POJ2723】Get Luffy Out - 二分+2-SAT
题面描述 Ratish is a young man who always dreams of being a hero. One day his friend Luffy was caught by ...
- gcc手动安装
Linux下: 手动安装gcc需要5个基础包 百度网盘链接:链接:包链接 密码:izxj 按照以上顺序安装:rpm -ivh 包名 为什么要手动安装呢,因为遇到这个情况:linux服务器没有权限连 ...