引言

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、文件上传原理

文件上传的原理如下图:

  1. Client 询问 Tracker 可以上传到哪个 Storage。
  2. Tracker 返回一台可用的 Storage 连接信息。
  3. Client 直接与 Storage 通信,完成文件上传。
  4. Storage 保存文件以后,返回 Client 文件标识(组名、文件名)。

4、文件下载原理

文件下载原理如下图:

  1. Client 询问 Tracker 下文文件的 Storage,参数为文件标识(组名、文件名)。
  2. Tracker 返回一台可用的 Storage。
  3. 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 号之后就停止更新了,最近又开始更新代码了,看样子要维护了啊。

简单的对客户端进行了连接池的封装,方便使用。

  • 系统启动,池子管理连接
  • 心跳确认连接是否可靠
  • 构造器模式创建连接池
  • 回调方式使用客户端

源码地址:

ClawHub/FastDFS-Pool

以下为核心代码:

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 V5.12 分布式文件系统介绍

tobato/FastDFS_Client 的 wiki

分布式文件存储:FastDFS简单使用与原理分析的更多相关文章

  1. 分布式文件存储FastDFS(一)初识FastDFS

    一.FastDFS简单介绍 FastDFS是一款开源的.分布式文件系统(Distributed File System),由淘宝开发平台部资深架构师余庆开发.作为一个分布式文件系统,它对文件进行管理. ...

  2. (转) 分布式文件存储FastDFS(一)初识FastDFS

    http://blog.csdn.net/xingjiarong/article/details/50559849 一.FastDFS简介 FastDFS是一款开源的.分布式文件系统(Distribu ...

  3. Centos7部署分布式文件存储(Fastdfs)

    目录 FastDFS介绍 楼主目标:前可H5撩妹,后可Linux搞运维 环境:Centos7 软件: 软件链接: 安装前所有准备,上传软件到Centos7上的/opt的目录下 安装依赖软件和类库(安装 ...

  4. 分布式文件存储FastDFS(七)FastDFS配置文件具体解释

    配置FastDFS时.改动配置文件是非常重要的一个步骤,理解配置文件里每一项的意义更加重要,所以我參考了大神的帖子,整理了配置文件的解释.原帖例如以下:http://bbs.chinaunix.net ...

  5. (转) 分布式文件存储FastDFS(七)FastDFS配置文件详解

    http://blog.csdn.net/xingjiarong/article/details/50752586 配置FastDFS时,修改配置文件是很重要的一个步骤,理解配置文件中每一项的意义更加 ...

  6. (转)分布式文件存储FastDFS(四)配置fastdfs-apache-module

    http://blog.csdn.net/xingjiarong/article/details/50560605 在前边我们已经配置好了FastDFS的环境,但是此时的FastDFS还不能通过htt ...

  7. (转)分布式文件存储FastDFS(三)FastDFS配置

    http://blog.csdn.net/xingjiarong/article/details/50559768 在上一节中我们一起搭建了一个单节点的FastDFS系统,但是仅仅将系统搭建起来是远远 ...

  8. (转)分布式文件存储FastDFS(二)FastDFS安装

    http://blog.csdn.net/xingjiarong/article/details/50559761 在前面的一篇中,我们分析了FastDFS的架构,知道了FastDFS是由客户端,跟踪 ...

  9. (转)分布式文件存储FastDFS(六)FastDFS多节点配置

    http://blog.csdn.net/xingjiarong/article/details/50759918 前面几篇关于FastDFS的博客中介绍了如何在一台机器上搭建一个简易的FastDFS ...

随机推荐

  1. LInux下Posix的传统线程示例

    简介 Linux线程是需要连接pthreat库,线程的使用比进程更灵活,需要注意的是线程间的互斥,或者说是资源共享问题. C++11之后,C++标准库也引入了线程,并且使用非常方便,以后再介绍,这里先 ...

  2. 一文说通C#中的异步编程补遗

    前文写了关于C#中的异步编程.后台有无数人在讨论,很多人把异步和多线程混了. 文章在这儿:一文说通C#中的异步编程 所以,本文从体系的角度,再写一下这个异步编程.   一.C#中的异步编程演变 1. ...

  3. Java 程序员生产神器 IDEA 的常用快捷键、插件及设置

    对于 Java 程序员来说,使用 IDEA 集成环境是最称手的.优点不多讲,用过的人都知道.IDEA 虽好,但为了充分利用 IDEA 的优势,我分享一下我常用快捷键.插件和设置. 常用快捷键 Ctrl ...

  4. Spring Cloud 之服务注册中心高可用

    服务注册中心高可用 服务注册中心 eureka-server 高可用实施 版本 Spring Boot 版本 # Spring Boot 版本: <parent> <groupId& ...

  5. Docker-Compose介绍,安装和使用

    Docker-Compose 介绍 有时候运行一个镜像需要大量的参数,可以通过Docker-Compose编写这些参数.而且Docker-Compose可以版主我们批量管理容器,这些信息值需要通过一个 ...

  6. Python安装工具

    1.官网下载地址是:https://www.python.org/downloads/  默认下载安装时记得勾选配置PATH路径 PIP工具包(我是选择Python 3.5的) 2.Windows 下 ...

  7. 03-java实现循环链表

    03java实现循环链表 本人git https://github.com/bigeyes-debug/Algorithm 一丶单向循环链表 就是为尾节点指向头结点 二丶单向循环链表的接口设计 比较单 ...

  8. 关于手机数码圈KOL的一两点感想

    复工以来,高峰时段9号线地铁上的人依旧不少,安全距离啥的肯定是不用想了,只是从原来的4G手机换成5G手机以后在某些站能接收到5G信号,我终于能在一些原来根本没信号的站里愉快的刷一刷微博和酷安了. 但是 ...

  9. java流程控制语句switch

    switch 条件语句也是一种很常用的选择语句,它和if条件语句不同,它只能针对某个表达 式的值作出判断,从而决定程序执行哪一段代码. 格式: switch (表达式){ case 目标值1: 执行语 ...

  10. flutter开发体验

    flutter 介绍 flutter 是一种跨平台UI开发框架.这方面类似框架有: weex: Weex是一个可以使用现代化的 Web 技术开发高性能原生应用的框架. React Native: Re ...