当前位置: 首页 > news >正文

FastDFS之快速入门、上手

知识概念

分布式文件系统

通过计算机网络将各个物理存储资源连接起来。通过分布式文件系统,将网络上任意资源以逻辑上的树形结构展现,让用户访问网络上的共享文件更见简便。

文件存储的变迁:

  • 直连存储:直接连接与存储,扩展性、灵活性差。如Tomcat、nginx。
  • 中心化存储:网络互联。
  • 分布式存储:资源存储在多个服务器,这个存储资源构成一个虚拟的存储设备。

常见的DFS

  • FastDFS :开源的轻量级分布式文件系统;
  • HDFS : Hadoop 子项目, Hadoop 的存储系统。
  • Taobao FileSystem :高扩展、高可用、高性能、面向互联网服务的分布式文件系统,针对海量非结构化数据,构建在普通linux机器集群上,提供高可靠、高并发的存储访问。
    • 为淘宝提供海量小文件存储,通常不超1M。
    • 采用HA架构和平滑扩容。

HA架构:通过设计,减少系统不可用的时间。通过 冗余(集群) + 自动故障转移来实现。

  • GridFS:mongodb内置功能。文件分成两份:索引和文件内容。它们存储在集合中,文件内容等分成若干块存储在文档中。一般以4M作为分块存储单位。
  • Google File System :非开源。
  • MogileFS : 由Six Apart开发,广泛应用在 包括LiveJournal等web2.0站点上 。
文件系统FastDFSHDFSTFSMogileFS
数据存储 方式文件/块文件文件文件
集群通讯 协议私有协议私有协议私有协议Http
扩容支持支持支持支持
冗余备份支持支持支持不 支持
单点故障不存在存在存在存在
跨集群同 步部分支持不支持支持不支持
开发语言CJavaC++Perl
适合类型4KB - 500MB大文件所有文件海量小图片
复杂度简单简单复杂复杂
易用性安装简单,社区 活跃安装简单,文档 专业安装复杂,文档 较少安装复杂,文档 较少
研发团队国内开发者-余庆ApacheAlibabaDanga Interactive
FUSE不支持支持不支持支持
POSIX不支持支持无资料不支持

常见DFS提供商

  • 阿里OSS
  • 七牛云存储
  • 百度云存储

FastDFS简介

FastDFS是用C语言编写的一款开源的分布式文件系统,它是由淘宝资深架构师余庆编写并开源。 FastDFS专为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高 性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。

功能概况

文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡 的问题。特别适合以中小文件( 建议范围: 4KB 到 500MB ) 为载体的在线服务,如:相册网站、视 频网站等等

架构

FastDFS架构包括 Tracker Server和Storage Server 。 Tracker Server负责处理客户端的文件上传、下载请求,通过调度,追踪定位 Storage Server 目标,最后由其完成文件下载、上传。
image.png

Tracker Server

作用是负载均衡和调度。在FastDFS集群中,可以有多台Tracker Server 同时提供服务,不存在单点故障。

Storage Server

处理文件存储,使用操作系统的文件系统管理文件。
采用分组存储方式,集群由多个一个或多个分组组成,集群容量是集群内所有组的总和,不同组之间不会互相通信,同组内相互连接同步文件(所以组的容量由组内最小容量的节点决定)。
使用分组的方式,比较灵活易扩展。客户端可以直接指定上传的组,也可以由Tracker进行调度;当访问压力大的时候,也可以通过增加组内存储服务器来提高服务能力;当容量不足时,可以增加分组,提高容量。

Storage 状态收集

Storage会连接所有Tracker,然后汇报自己的状态。,包括磁盘空间、文件同步情况、文件上传下载次数等统计信息。

文件上传流程

image.png
客户端拿到file_id之后,存储起来,后续通过file_id拿到文件。
file_id相当于一个索引,其文件索引信息包括:组名,虚拟磁盘路径,数据两级目录,文件名。

例如:group1/M00/00/00/wKjIgGNslmOAf5VSAACQjdb7ANw5904822

  • 组名:文件上传后所在的分组;
  • 虚拟磁盘路径:通过store_path指定的 Storage 虚拟路径。 store_path0(相当于一个组内节点) 是M00 ,了store_path1则是M01,以此类推。
  • 数据两级目录 : 在 虚拟磁盘路径下创建的两级目录,用于存储数据文件。
  • 文件名:由存储服务器根据特定信息(源存储服务器IP地址、文件创建时间戳、文件大小、随机数和文件拓展名等信息)生成。

文件下载流程

image.png

  • 通过组名, tracker 能快速锁定所在分组,然后 tracker 会选择一个合适的存储节点,并把节点信息返回给客户端。
  • 客户端访问存储服务器的时候,存储服务器可以通过文件虚拟路径数据两级目录来快速定位文件,并根据文件名找到访问的文件。

准备环境

开几个ubuntu18虚拟机:

节点IP域名端口开放
tracker1192.168.204.167tracker122122
tracker2192.168.204.168tracker222122
storage1192.168.204.169storage123000、8888
storage2192.168.204.170storage123000、8888

修改一下自己电脑的host文件:

192.168.204.167 tracker1
192.168.204.168 tracker2
192.168.204.169 storage1
192.168.204.170 storage2

下载镜像:
docker pull morunchang/fastdfs

https://hub.docker.com/r/morunchang/fastdfs

tracker

在tracker1、tracker2服务器运行下面命令(运行前检查tracker_data目录是否创建了)。
默认端口:22122。

docker run -d --name tracker -p 22122:22122 -v ~/tracker_data:/data/fast_data  --net=host morunchang/fastdfs sh tracker.sh

–net:支持 bridge/host/none/container 四种类型

storage

在storage1、storage2服务器运行下面命令(运行前检查storage_data、store_path目录是否创建了)。


docker run -d --name storage \
-v ~/storage_data:/data/fast_data \
-v ~/conf/nginx.conf:/etc/nginx/conf/nginx.conf \
--net=host -e GROUP_NAME=group1 \
-e TRACKER_IP=tracker1:22122,tracker2:22122 \
morunchang/fastdfs sh storage.sh
#user  nobody;
worker_processes  1;#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;#pid        logs/nginx.pid;events {worker_connections  1024;
}http {include       mime.types;default_type  application/octet-stream;#log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '#                  '$status $body_bytes_sent "$http_referer" '#                  '"$http_user_agent" "$http_x_forwarded_for"';#access_log  logs/access.log  main;sendfile        on;#tcp_nopush     on;#keepalive_timeout  0;keepalive_timeout  65;#gzip  on;server {listen       8888;server_name  localhost;#charset koi8-r;#access_log  logs/host.access.log  main;location / {root   html;index  index.html index.htm;}location ~ /M00 {root /data/fast_data/data;ngx_fastdfs_module;}#error_page  404              /404.html;# redirect server error pages to the static page /50x.html#error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}# proxy the PHP scripts to Apache listening on 127.0.0.1:80##location ~ \.php$ {#    proxy_pass   http://127.0.0.1;#}# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000##location ~ \.php$ {#    root           html;#    fastcgi_pass   127.0.0.1:9000;#    fastcgi_index  index.php;#    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;#    include        fastcgi_params;#}# deny access to .htaccess files, if Apache's document root# concurs with nginx's one##location ~ /\.ht {#    deny  all;#}}# another virtual host using mix of IP-, name-, and port-based configuration##server {#    listen       8000;#    listen       somename:8080;#    server_name  somename  alias  another.alias;#    location / {#        root   html;#        index  index.html index.htm;#    }#}# HTTPS server##server {#    listen       443 ssl;#    server_name  localhost;#    ssl_certificate      cert.pem;#    ssl_certificate_key  cert.key;#    ssl_session_cache    shared:SSL:1m;#    ssl_session_timeout  5m;#    ssl_ciphers  HIGH:!aNULL:!MD5;#    ssl_prefer_server_ciphers  on;#    location / {#        root   html;#        index  index.html index.htm;#    }#}}

整合SpringBoot

去github拉取源码,然后mvn clean install到本地仓库(官方没有发布到maven中心仓库),最后再引入依赖:

        <dependency>		<groupId>org.csource</groupId><artifactId>fastdfs-client-java</artifactId><version>1.30-SNAPSHOT</version></dependency>

image.png

# http连接超时时间
connect_timeout = 2
# tracker与storage网络通信超时时间
network_timeout = 30
charset = UTF-8
http.tracker_http_port = 80
http.anti_steal_token = no
http.secret_key = FastDFS1234567890
# tracker服务器地址,可以重复配置多个
tracker_server = tracker1:22122
tracker_server = tracker2:22122# 连接池配置
connection_pool.enabled = true
connection_pool.max_count_per_entry = 500
connection_pool.max_idle_time = 3600
connection_pool.max_wait_time_in_ms = 1000
package com.example.demofastdfs.test;import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;import java.io.*;
import java.util.Arrays;/*** @className: FastDFSDemo* @description: TODO 类描述* @author: liangshijie* @date: 2023/3/5**/
public class FastDFSDemo {private static final String CONF_NAME = "fdfs_client.conf";private StorageClient storageClient;private TrackerServer trackerServer;@Beforepublic void initStorageClient() throws Exception {ClientGlobal.init(CONF_NAME);System.out.println("network_timeout=" +ClientGlobal.g_network_timeout + "ms");System.out.println("charset=" + ClientGlobal.g_charset);TrackerClient tracker = new TrackerClient();trackerServer = tracker.getTrackerServer();StorageServer storageServer = new StorageServer("storage1", 23000, 0);storageClient = new StorageClient(trackerServer, storageServer);
//        storageClient = new StorageClient(trackerServer, storageServer);}/*** 测试上传文件*/@Testpublic void upload() throws Exception {// http://storage2:23000/group1/M00/00/00/wKjMqWQHVleAFzK7AAAWWKCNj-E2720984.jpgNameValuePair[] metaList = new NameValuePair[1];String local_filename = "dog.png";metaList[0] = new NameValuePair("fileName", local_filename);File file = new File("C:\\Users\\admin\\Desktop\\dog.png");InputStream inputStream = new FileInputStream(file);int length = inputStream.available();byte[] bytes = new byte[length];inputStream.read(bytes);String[] result = storageClient.upload_file(bytes, "jpg", metaList);
//        String[] result = storageClient.upload_file(bytes, null, metaList);System.out.println("result {}" + Arrays.asList(result));}//查询文件@Testpublic void testQueryFile() throws IOException, MyException {
//        group1, M00/00/00/wKjMqWQGk_WAesAEAAAWWKCNj-E4269595FileInfo fileInfo = storageClient.query_file_info("group1", "M00/00/00/wKjMqWQGk_WAesAEAAAWWKCNj-E4269595");System.out.println(fileInfo);}/*** 测试下载*/@Testpublic void download() throws Exception {String[] uploadresult = {"group1","M00/00/00/wKjMqWQGk_WAesAEAAAWWKCNj-E4269595"};byte[] result = storageClient.download_file(uploadresult[0],uploadresult[1]);String local_filename = "dog_two.png";
//文件写入磁盘writeByteToFile(result, local_filename);File file = new File(local_filename);System.out.println("file.isFile = " + file.isFile());}@Afterpublic void closeClient() {System.out.println("close connection");if (storageClient != null) {try {storageClient.close();} catch (Exception e) {e.printStackTrace();} catch (Throwable e) {e.printStackTrace();}}}public void writeByteToFile(byte[] fbyte, String fileName) throwsIOException {BufferedOutputStream bos = null;FileOutputStream fos = null;File file = new File(fileName);try {fos = new FileOutputStream(file);bos = new BufferedOutputStream(fos);bos.write(fbyte);} catch (Exception e) {e.printStackTrace();} finally {if (bos != null) {bos.close();}if (fos != null) {fos.close();}}}}

测试地址

http://storage1:8888/group1/M00/00/00/wKjMqWQHWfqAGM9mAAAWWKCNj-E813.jpg

相关文章:

FastDFS之快速入门、上手

知识概念 分布式文件系统 通过计算机网络将各个物理存储资源连接起来。通过分布式文件系统&#xff0c;将网络上任意资源以逻辑上的树形结构展现&#xff0c;让用户访问网络上的共享文件更见简便。 文件存储的变迁&#xff1a; 直连存储&#xff1a;直接连接与存储&#xf…...

Vue 中的 ref 与 reactive:让你的应用更具响应性(中)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…...

【数据库基础】Mysql与Redis的区别

看到一篇不错的关于“Mysql与Redis的区别”的文章&#xff0c;转过来记录下~ 文章目录 一、数据库类型二、运行机制三、什么是缓存数据库呢&#xff1f;四、优缺点比较五、区别总结六、数据可以全部直接用Redis储存吗&#xff1f;参考资料 一、数据库类型 Redis&#xff1a;NOS…...

JVM工作原理与实战(六):类的生命周期-连接阶段

专栏导航 JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、类的生命周期 1.加载&#xff08;Loading&#xff09; 2.连接&#xff08;Linking&#xff09; 3.初始化&#xff08;Initialization&#xff09; 4.使用&#xff08;Using&…...

【OCR】 - Tesseract OCR在Windows系统中安装

Tesseract OCR 在Windows环境下安装Tesseract OCR&#xff08;Optical Character Recognition&#xff09;通常包括以下几个步骤&#xff1a; 下载Tesseract 访问Tesseract的GitHub发布页面&#xff1a;https://github.com/tesseract-ocr/tesseract/releases找到适合你操作系…...

YOLOv8改进 | 损失函数篇 | SlideLoss、FocalLoss分类损失函数助力细节涨点(全网最全)

一、本文介绍 本文给大家带来的是分类损失 SlideLoss、VFLoss、FocalLoss损失函数,我们之前看那的那些IoU都是边界框回归损失,和本文的修改内容并不冲突,所以大家可以知道损失函数分为两种一种是分类损失另一种是边界框回归损失,上一篇文章里面我们总结了过去百分之九十的…...

计算机网络试题——填空题(附答案)

在OSI模型中&#xff0c;第一层是____________层。 答案&#xff1a;物理&#xff08;Physical&#xff09; TCP协议是一种_____________连接的协议。 答案&#xff1a;面向连接&#xff08;Connection-oriented&#xff09; IPv6地址的位数是____________。 答案&#xff1a;1…...

第二证券:股票私募仓位指数创近八周新高

1月8日&#xff0c;A股几大首要指数全线收跌&#xff0c;上证指数收于日内最低点2887.54点&#xff0c;间隔上一年5月份的阶段高点3418.95点现已跌去了15.54%。 不过&#xff0c;虽然商场仍未清晰止跌&#xff0c;私募基金们却现已进场“抄底”。私募排排网最新发布的私募仓位…...

35-javascript基础,引入方式;变量命名规范

html分为三部分&#xff1b;结构html&#xff0c;表现css&#xff0c;行为js&#xff1b;js就是javascript js包含三部分&#xff1a; ECMAScript&#xff1a;简称ES&#xff0c;ES5&#xff0c;ES6核心语法 DOM&#xff1a;获取和操作html元素的标准方法&#xff1b;BOM&am…...

笔试案例2

文章目录 1、笔试案例22、思维导图 1、笔试案例2 09&#xff09;查询学过「张三」老师授课的同学的信息 selects.*,c.cname,t.tname,sc.score from t_mysql_teacher t, t_mysql_course c, t_mysql_student s, t_mysql_score sc where t.tidc.cid and c.cidsc.cid and sc.sids…...

【嵌入式-网络编程】vmware中使用UDP广播失败问题

问题描述&#xff1a; 自己在vmware中搭建了2台虚拟机&#xff0c;虚拟机A向虚拟机A和虚拟机B发送广播信息&#xff0c;接收端在虚拟机A和虚拟机B&#xff0c;这个时候&#xff0c;由于没配置sin.sin_addr.s_addr htonl(INADDR_ANY);&#xff0c;而是配置的inet_pton(AF_INET,…...

2020年认证杯SPSSPRO杯数学建模D题(第二阶段)让电脑桌面飞起来全过程文档及程序

2020年认证杯SPSSPRO杯数学建模 D题 让电脑桌面飞起来 原题再现&#xff1a; 对于一些必须每天使用电脑工作的白领来说&#xff0c;电脑桌面有着非常特殊的意义&#xff0c;通常一些频繁使用或者比较重要的图标会一直保留在桌面上&#xff0c;但是随着时间的推移&#xff0c;…...

vue3 修饰符大全(近万字长文)

系列文章目录 TypeScript 从入门到进阶专栏 文章目录 系列文章目录前言一、事件修饰符&#xff08;Event Modifiers&#xff09;1、.stop&#xff08;阻止事件冒泡&#xff09;2、.prevent&#xff08;阻止事件的默认行为&#xff09;3、.capture&#xff08;使用事件捕获模式…...

HarmonyOS@State装饰器:组件内状态

State装饰器&#xff1a;组件内状态 State装饰的变量&#xff0c;或称为状态变量&#xff0c;一旦变量拥有了状态属性&#xff0c;就和自定义组件的渲染绑定起来。当状态改变时&#xff0c;UI会发生对应的渲染改变。 在状态变量相关装饰器中&#xff0c;State是最基础的&…...

如何让GPT支持中文

上一篇已经讲解了如何构建自己的私人GPT&#xff0c;这一篇主要讲如何让GPT支持中文。 privateGPT 本地部署目前只支持基于llama.cpp 的 gguf格式模型&#xff0c;GGUF 是 llama.cpp 团队于 2023 年 8 月 21 日推出的一种新格式。它是 GGML 的替代品&#xff0c;llama.cpp 不再…...

使用开源通义千问模型(Qwen)搭建自己的大模型服务

目标 1、使用开源的大模型服务搭建属于自己的模型服务&#xff1b; 2、调优自己的大模型&#xff1b; 选型 采用通义千问模型&#xff0c;https://github.com/QwenLM/Qwen 步骤 1、下载模型文件 开源模型库&#xff1a;https://www.modelscope.cn/models mkdir -p /data/…...

Java工程师面试题解析与深度探讨

Java工程师面试题解析与深度探讨 第一部分&#xff1a;引言 Java作为一门广泛应用的编程语言&#xff0c;拥有庞大的生态系统&#xff0c;Java工程师因此成为众多企业追逐的目标。而在Java工程师的招聘中&#xff0c;面试是了解候选人技能和经验的核心环节。本文将深入探讨一…...

Linux下安装JET2

0. 说明&#xff1a; JET2是一个基于Joint Evolutionary Trees的利用序列和结构信息预测蛋白质界面的软件&#xff0c;详情见: http://www.lcqb.upmc.fr/JET2/JET2.html&#xff0c;http://www.lgm.upmc.fr/JET/JET.html 和 https://doi.org/10.1371/journal.pcbi.1004580 本…...

【PostgreSQL】表管理-表继承

PostgreSQL 表继承 PostgreSQL 实现了表继承&#xff0c;这对于数据库设计人员来说是一个有用的工具。&#xff08;SQL&#xff1a;1999 及更高版本定义了类型继承功能&#xff0c;该功能在许多方面与此处描述的功能不同。 让我们从一个例子开始&#xff1a;假设我们正在尝试…...

Dijkstra算法——邻接矩阵实现+路径记录

本文是在下面这篇文章的基础上做了一些补充&#xff0c;增加了路径记录的功能。具体Dijkstra的实现过程可以参考下面的这篇文章。 [jarvan&#xff1a;Dijkstra算法详解 通俗易懂](Dijkstra算法详解 通俗易懂 - jarvan的文章 - 知乎 https://zhuanlan.zhihu.com/p/338414118) …...

VoWiFi 核心网元与信令流程全解析

1. VoWiFi技术入门&#xff1a;从Wi-Fi打电话的秘密 第一次用手机连Wi-Fi打电话时&#xff0c;我盯着信号栏的"Wi-Fi Calling"标志愣了半天——这玩意儿居然真能绕过蜂窝网络&#xff1f;后来才知道&#xff0c;这就是VoWiFi&#xff08;Voice over Wi-Fi&#xff0…...

从90%到99%:实战提升Tesseract在C++项目中的识别准确率(附调参技巧)

从90%到99%&#xff1a;实战提升Tesseract在C项目中的识别准确率&#xff08;附调参技巧&#xff09; 在工业级文档处理系统中&#xff0c;我们常遇到这样的困境&#xff1a;测试集上的OCR识别准确率卡在90%左右&#xff0c;而业务部门要求必须达到99%以上才能上线。去年负责某…...

django-flask基于python实验室资产管理系统 实验室器材租赁系统

目录基于Python的实验室资产与器材租赁管理系统&#xff08;Django/Flask&#xff09;摘要关于博主开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;基于Python的实验室资产与器材租赁管理系统…...

IPBan快速入门:一键安装配置,立即阻止僵尸网络入侵

IPBan快速入门&#xff1a;一键安装配置&#xff0c;立即阻止僵尸网络入侵 【免费下载链接】IPBan Since 2011, IPBan is the worlds most trusted, free security software to block hackers and botnets. With both Windows and Linux support, IPBan has your dedicated or …...

VSIPL:嵌入式信号处理的跨平台解决方案

1. VSIPL&#xff1a;嵌入式信号处理的工业级解决方案在实时嵌入式多计算机系统的开发中&#xff0c;代码的可移植性一直是困扰工程师的难题。1990年代末&#xff0c;来自政府、学术界和工业界的专家们共同创建了VSIPL&#xff08;Vector Scalar Image Processing Library&…...

智能体工程方法论:从AI辅助编码到可控软件开发的范式升级

1. 项目概述&#xff1a;从“氛围编码”到“智能体工程”的范式升级如果你和我一样&#xff0c;是一名长期在一线写代码的开发者&#xff0c;过去两年里&#xff0c;你肯定经历过那种“过山车”般的感觉。先是惊叹于AI助手&#xff08;无论是GitHub Copilot、Cursor还是Claude …...

AI助手状态可视化:像素风办公室看板的设计、部署与集成指南

1. 项目概述&#xff1a;一个像素风的AI办公室看板如果你和我一样&#xff0c;日常工作中重度依赖AI助手&#xff0c;比如OpenClaw&#xff0c;那你可能也遇到过这样的困惑&#xff1a;当AI在后台默默执行一个长任务时&#xff0c;你完全不知道它进行到哪一步了。是卡住了&…...

Groundhog:基于Git仓库的开发者时间自动追踪工具

1. 项目概述&#xff1a;一个面向开发者的时间管理利器如果你是一名开发者&#xff0c;或者你的工作与代码、项目、任务紧密相关&#xff0c;那么你一定对“时间都去哪儿了”这个问题深有感触。我们每天在各种编辑器、终端、浏览器标签页之间切换&#xff0c;处理着功能开发、B…...

轻量级视频稳定技术:EfficientMotionPro与OnlineSmoother解析

1. 轻量级视频稳定技术概述视频稳定技术是现代计算机视觉领域的重要研究方向&#xff0c;其核心目标是消除因相机抖动导致的画面不稳定现象。传统视频稳定方法通常依赖于复杂的光流计算或3D场景重建&#xff0c;这些方法虽然效果稳定&#xff0c;但计算开销巨大&#xff0c;难以…...

RPGMZ 万能通用钩子代码 插入自己的代码逻辑

const prevUpdate SceneManager._scene.update; SceneManager._scene.update function() {prevUpdate.call(this); // 保留原版// 你的任意代码SceneManager._scene.update prevUpdate; // 用完归还 };例子1 消息框对话 如何插入自己的对话内容const prevUpdate SceneMan…...