分布式文件存储: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 ...
随机推荐
- NuGet Package Explorer 中文版
Id:NuGet Package Explorer 中文版 Description:基于原版 5.7.170 的绿色中文版,无任何‘添加剂’ Version:5.7.170 Download:Gith ...
- CentOS7安装Redis的两种方式
1. 源码安装方式(不推荐): https://www.cnblogs.com/zuidongfeng/p/8032505.html https://www.cnblogs.com/zerotomax ...
- GitLab Admin Area 500 Error
GitLab Admin Area 500 Error GitLab Admin Area Settings 菜单全部报错 500 解决方法 执行: gitlab-rake cache:clear # ...
- 2020重新出发,JAVA入门,关键字&保留字
关键字 & 保留字 关键字(或者保留字)是对编译器有特殊意义的固定单词,不能在程序中做其他目的使用. 关键字具有专门的意义和用途,和自定义的标识符不同,不能当作一般的标识符来使用.例如, cl ...
- java SFTP工具类
需要导入jsch-0.1.52.jar import java.io.File; import java.io.FileInputStream; import java.io.FileOutputSt ...
- socket传输图片用shutdownoutput()之后无法继续传输数据
socket传输图片用shutdownoutput()之后无法继续传输数据前言java的socket是一个全双工套接字,任何的输入流或输出流的close()都会造成Socket关闭.使用java服务器 ...
- ASP.NET Core 奇技淫巧之接口代理转发
前言 先讲讲本文的开发背景吧.. 在如今前后端分离的大背景下,咱的客户又有要求啦~ 要前后端分离~ 然因为种种原因..没办法用用纯前端的框架(其实是学习成本高,又没钱请前端开发人员)... 所以最终决 ...
- python设计模式之修饰器模式
python设计模式之修饰器模式 无论何时我们想对一个对象添加额外的功能,都有下面这些不同的可选方法. [ ] 如果合理,可以直接将功能添加到对象所属的类(例如,添加一个新的方法) [ ] 使用组合 ...
- 装机备忘录:VS Code 常用插件
VS Code 常用插件推荐 1.基本的代码补全 2.git 扩展工具,可以看到代码的每一行 是谁修改?什么时候修改? 修改的版本号? 修改的注释? 非常好的一个工具 3.括号颜色改变工具,可以改变括 ...
- Uni-app从入门到实战
前言 uni-app是一个使用vue.js开发跨平台应用的前端框架,开发者只需要编写一套代码,便可以发布到IOS.Android和微信小程序等多个平台.所以我打算学习下这个框架,快速浏览了一遍官网之后 ...