分布式文件存储与数据缓存(一)| FastDFS

目录

分布式文件系统

业务继续发展,单台服务器存储和响应也很快到达了瓶颈,新的业务需要文件访问具有高响应性、高可用性来支持系统。

优点:

扩展能力: 毫无疑问,扩展能力是一个分布式文件系统最重要的特点;

高可用性: 在分布式文件系统中,高可用性包含两层,一是整个文件系统的可用性,二是数据的完整和一致性;

弹性存储: 可以根据业务需要灵活地增加或缩减数据存储以及增删存储池中的资源,而不需要中断系统运行。
缺点: 系统复杂度稍高,需要更多服务器

FastDFS概述_简介

FastDFS是一个开源的轻量级分布式文件系统。它解决了大数据量存储和负载均衡等问题。特别适合以中小文件(建议范围:4KB <file_size <500MB)为载体的在线服务,如相册网站、视频网站等等。

FastDFS特性:

  • 文件不分块存储,上传的文件和OS文件系统中的文件一一对应
  • 支持相同内容的文件只保存一份,节约磁盘空间
  • 下载文件支持HTTP协议,可以使用内置Web Server,也可以和其他Web Server配合使用
  • 支持在线扩容
  • 支持主从文件

分布式文件服务提供商

  1. 阿里的OSS
  2. 七牛云存储
  3. 百度云储存

FastDFS概述_核心概念

FastDFS服务端有三个角色:跟踪服务器(tracker)、存储服务器(storage)和客户端(client)。

tracker

跟踪服务器,主要做调度工作,起负载均衡的作用。在内存中记录集群中所有存储组和存储服务器的状态信息,是客户端和数据服务器交互的枢纽。

storage

存储服务器(又称:存储节点或数据服务器),文件和文件属性(meta data)都保存到存储服务器上。Storage server直接利用OS的文件系统调用管理文件。

client

客户端,作为业务请求的发起方,通过专有接口,使用TCP/IP协议与跟踪器服务器或存储节点进行数据交互。FastDFS向使用者提供基本文件访问接口,比如upload、download、append、delete等,以客户端库的方式提供给用户使用。

group

组, 也可称为卷。 同组内服务器上的文件是完全相同的 ,同一组内的storage server之间是对等的, 文件上传、 删除等操作可以在任意一台storage server上进行 。

流程:

Tracker相当于FastDFS的大脑,不论是上传还是下载都是通过tracker来分配资源;客户端一般可以使用Ngnix等静态服务器来调用或者做一部分的缓存;存储服务器内部分为卷(或者叫做组),卷于卷之间是平行的关系,可以根据资源的使用情况随时增加,卷内服务器文件相互同步备份,以达到容灾的目的。

FastDFS概述_上传机制

首先客户端请求Tracker服务获取到存储服务器的ip地址和端口,然后客户端根据返回的IP地址和端口号请求上传文件,存储服务器接收到请求后生产文件,并且将文件内容写入磁盘并返回给客户端file_id、路径信息、文件名等信息,客户端保存相关信息上传完毕。

内部机制如下

1、选择Tracker server

当集群中不止一个Tracker server时,由于Tracker之间是完全对等的关系,客户端在upload文件时可以任意选择一个trakcer。
2、选择Storage server

当选定Group后,Tracker会在Group内选择一个Storage Server给客户端
3、选择Storage path

当分配好Storage Server后,客户端将向Storage发送写文件请求,Storage将会为文件分配一个数据存储目录。

注意:

剩余存储空间最多的优先。

4、生成Fileid

选定存储目录之后,Storage会为文件生一个Fileid,由StorageServer Ip、文件创建时间、文件大小、文件crc32和一个随机数拼接而成,然后将这个二进制串进行base64编码,转换为可打印的字符串。
5、生成文件名

当文件存储到某个子目录后,即认为该文件存储成功,接下来会为该文件生成一个文件名,文件名由group、存储目录、两级子目录、fileid、文件后缀名(由客户端指定,主要用于区分文件类型)拼接而成。

FastDFS概述_下载机制

客户端带上文件名信息请求Tracker服务获取到存储服务器的ip地址和端口,然后客户端根据返回的IP地址和端口号请求下载文件,存储服务器接收到请求后返回文件给客户端。

内部机制如下

1、client询问tracker下载文件的storage,参数为文件标识(组名和文件名)
2、tracker返回一台可用的storage
3、client直接和storage通讯完成文件下载

FastDFS环境搭建_Linux

下载安装gcc

sh 复制代码
 yum install gcc-c++ perl-devel pcre-devel openssl-devel zlib-devel wget

下载安装FastDFS

sh 复制代码
wget https://github.com/happyfish100/fastdfs/archive/V6.06.tar.gz

下载安装FastDFS依赖

sh 复制代码
wget https://github.com/happyfish100/libfastcommon/archive/V1.0.43.tar.gz

解压缩依赖tar包

sh 复制代码
tar -zxvf V1.0.43.tar.gz -C /usr/local
tar -zxvf V5.11.tar.gz -C /usr/local

编译并安装libfastcommon

sh 复制代码
cd /usr/local/libfastcommon-1.0.43/
 ./make.sh && ./make.sh install

编译并安装FastDFS

sh 复制代码
cd /usr/local/fastdfs-6.06
./make.sh && ./make.sh install

进入etc目录下复制配置文件

sh 复制代码
cd /etc/fdfs/
cp client.conf.sample client.conf
cp storage.conf.sample storage.conf
cp tracker.conf.sample tracker.conf

创建tracker服务

创建tracker目录

sh 复制代码
mkdir -p /data/fastdfs/tracker

修改配置文件

sh 复制代码
vim /etc/fdfs/tracker.conf

disabled=false                 #启用配置文件
port=22122                     #设置 tracker的端口号
base_path=/data/fastdfs/tracker #设置 tracker的数据文件和日志目录(需预先创建)
http.server_port=8888           #设置 http 端口号

启动tracker服务

sh 复制代码
/etc/init.d/fdfs_trackerd start

检查tracker服务

sh 复制代码
netstat -lntup |grep fdfs

创建storage服务

创建storage目录

sh 复制代码
mkdir -p /data/fastdfs/base
mkdir -p /data/fastdfs/storage

修改配置文件

sh 复制代码
vim /etc/fdfs/storage.conf

disabled=false                       #启用配置文件
group_name=group1                     #组名,根据实际情况修改
port=23000                           #设置storage 的端口号
base_path=/data/fastdfs/base         #设置storage 的日志目录(需预先创建)
store_path_count=1                   #存储路径个数,需要和 store_path 个数匹配
store_path0=/data/fastdfs/storage       #存储路径
tracker_server=172.31.16.121:22122    #tracker 服务器的 IP 地址和端口号
http.server_port=8888                 #设置storage上启动的http服务的端口号,如安装的nginx的端口号

启动storage服务

sh 复制代码
/etc/init.d/fdfs_storaged start

查看storage服务

sh 复制代码
netstat -lntup |grep fdfs

修改Client配置文件

sh 复制代码
vim /etc/fdfs/client.conf

connect_timeout=30
network_timeout=60
base_path=/data/fastdfs/client      # 日志路径
tracker_server=192.168.66.100:22122    # 追踪服务器的IP,有多个服务器可以另一行

创建日志目录

sh 复制代码
mkdir -p /data/fastdfs/client

FastDFS指令

上传指令

指令参数

复制代码
fdfs_upload_file <config_file> <local_filename> [storage_ip:port] [store_path_index]

参数含义:

  1. <config_file> :配置文件路径
  2. <local_filename>:本地文件路径
  3. [storage_ip:port]:(可选参数)
  4. [store_path_index] :(可选参数)

指令使用

复制代码
[root@tracker fdfs]# fdfs_upload_file /etc/fdfs/client.conf 上传的文件路径

上传文件后会返回文件在FastDFS中的唯一文件标识,即卷名+文件名

下载指令

指令参数

复制代码
fdfs_download_file <config_file> <file_id>[local_filename] [<download_offset><download_bytes>]

参数含义:

  1. <config_file> :配置文件路径
  2. <file_id> :文件在FastDFS中的唯一文件标识,即卷名+文件名
  3. [local_filename] :文件下载地址
  4. <download_offset> :(可选参数)文件下载开始时间
  5. <download_bytes> :(可选参数)文件下载的字节数

指令使用

复制代码
[root@tracker fdfs]# fdfs_download_file /etc/fdfs/client.conf 上传时返回的唯一文件标识 指定位置

查看文件信息指令

指令参数

复制代码
fdfs_file_info <config_file> <file_id>

参数含义:

  1. <config_file> :配置文件路径
  2. <file_id>:文件在FastDFS中的唯一文件标识,即卷名+文件名

指令使用

root@tracker fdfs\]# fdfs_file_info /etc/fdfs/client.conf 文件在FastDFS中的唯一文件标识 ### 删除指令 #### 指令参数 fdfs_delete_file > **参数含义:** > > 1. `` :配置文件路径 > 2. ``:文件在FastDFS中的唯一文件标识,即卷名+文件名 #### 指令使用 [root@tracker fdfs]# fdfs_delete_file /etc/fdfs/client.conf 文件在FastDFS中的唯一文件标识 > **注意:** > > 删除指令使用后,文件在该卷中的所有备份都会被删除,因为卷内的存储节点会相互同步,故慎用。 ## SpringBoot操作FastDFS ### 导入FastDFS依赖jar ```xml com.github.tobato fastdfs-client 1.26.5 ``` ### 配置springboot的application.yml配置文件 ```yml #### 分布式文件系统的配置 #### fdfs: # 超时时间 connect-timeout: 600 # 连接时间 so-timeout: 1500 tracker-list: - 192.168.52.136:22122 ``` ### 上传和下载文件操作 ```java @SpringBootTest class FastfdsDemoApplicationTests { // fastdfs 存储节点的客户端对象 @Autowired private FastFileStorageClient fastFileStorageClient; @Test /** * java api 对分布式文件系统上传文件操作 */ public void testUpload() throws FileNotFoundException { // 1. 获取本地文件 File file = new File("f:\\2.jpg"); // 2. 创建传输文件的输入流 FileInputStream inputStream = new FileInputStream(file); // 3. 上传文件 /* * 第一个参数:文件的输入流 * 第二个参数:文件的大小 * 第三个参数:文件的扩展名 * 第四个参数:文件的元数据 */ StorePath storePath = fastFileStorageClient.uploadFile(inputStream, file.length(), "jpg", null); // 4. 将文件名和卷名一起打印 System.out.println(storePath.getFullPath()); System.out.println("+++++++++++++++++++++++++++++"); System.out.println(storePath.getGroup() + " | " + storePath.getPath()); // group1 /M00/00/00/wKg0iGX1bSSAdrMgAAexV9rfK9A537.jpg // ++++++++++++++++++++++++++++ + // group1 | M00/00/00/wKg0iGX1bSSAdrMgAAexV9rfK9A537.jpg } /** * java api 对分布式文件系统下载文件操作 */ @Test public void testDownload() throws IOException { // 1. 下载文件 /* * 第一个参数:文件处于存储节点卷名 * 第二个参数:文件在存储节点的文件名 * 第三个参数:下载的回调函数 */ byte[] bytes = fastFileStorageClient.downloadFile("group1", "M00/00/00/wKg0iGX1bSSAdrMgAAexV9rfK9A537.jpg", new DownloadByteArray()); // 2. 创建文件的输出流 FileOutputStream fileOutputStream = new FileOutputStream("f:\\1.jpg"); // 3. 使用文件输出流将文件内筒字节数组写出 fileOutputStream.write(bytes); // 4. 刷新输出流 fileOutputStream.flush(); // 5. 关闭输出流 fileOutputStream.close(); } } ``` ## 前端文件上传到fastdfs ### 引入Thymeleaf视图解析器 ```xml org.springframework.boot spring-boot-starterthymeleaf org.springframework.boot spring-boot-starterweb ``` ### 编写index页面 引入wangEditor富文本编辑器 ```html wangEditor demo

欢迎使用 wangEditor 富文本编辑器

``` ### 编写Controller接口 ```java @RestController public class UploadController { // fastdfs 存储节点的客户端对象 @Autowired private FastFileStorageClient fastFileStorageClient; @PostMapping("upload") public void upload(MultipartFile file) throws IOException { // 1. 判断文件是否为空 if(file!=null){ // 2. 获取上传图片名字 String filename = file.getOriginalFilename(); // 3. 获取图片后缀 String fileSuffix = filename.substring(filename.lastIndexOf(".") + 1); // 4. 上传图片 StorePath storePath = fastFileStorageClient.uploadFile(file.getInputStream(), file.getSize(), fileSuffix, null); // 5. 创建成功会返回文件路径 System.out.println(storePath.getFullPath()); // TODO 保存到数据库 } } } ``` ## FastDFS集成Nginx ### FastDFS集成Nginx的2个原因 #### 为分布式文件系统提供Http服务支持 为分布式文件系统提供Http服务支持通过Nginx的web服务代理访问分布式文件系统的存储节点,从而实现通过http请求访问存储节点资源。 ![在这里插入图片描述](https://file.jishuzhan.net/article/1770109084448591874/5dd5bc0fee7ef14780698dec467f7452.webp) #### 解决复制延迟问题 由于FastDFS的同卷的存储节点之间需要同步,当文件尚未同步完成时,访问请求到达改节点,获取的数据将是未同步完的不完整数据,即为复制延迟问题。通过Nginx检测请求的存储节点的数据,若该存储节点的数据尚未同步完成,则将请求转发至数据的原存储节点,从而解决复制延迟问题。 ## FastDFS集成Nginx_环境搭建 ### 下载Fastdfs的Nginx模块包 ```sh cd /usr/local wget https://github.com/happyfish100/fastdfs-nginx-module/archive/V1.22.tar.gz tar -zxvf V1.22.tar.gz ``` ### 安装Nginx依赖文件 ```sh yum install -y gcc gcc-c++ zlib zlib-devel openssl openssl-devel pcre pcre-devel gd-devel epel-release ``` ### 下载Nginx软件包 ```sh wget https://nginx.org/download/nginx-1.19.2.tar.gz cd nginx-1.19.2/ ``` ### 配置Nginx服务器 ```sh #建立Makefile文件,检查Linux系统环境以及相关的关键属性。 ./configure --add-module=/usr/local/fastdfs-nginx-module-1.22/src/ #编译项目,主要将gcc源代码编译成可执行的目标文件 make #根据上一步骤编译完成的数据安装到预定的目录中。 make install ``` ### 将Fastdfs软件包里面的http.conf和mime.types拷贝到/etc/fdfs目录下 ```sh cp /usr/local/src/fastdfs-6.06/conf/mime.types /etc/fdfs/ cp /usr/local/src/fastdfs-6.06/conf/http.conf /etc/fdfs/ ``` ### 配置Nginx的fastdfs模块,并编辑文件 ```sh #拷贝文件 [root@localhost opt]cp /usr/local/fastdfs-nginx-module-1.22/src/mod_fastdfs.conf /etc/fdfs/ [root@localhost fdfs] vim mod_fastdfs.conf #保存日志目录 base_path=/data/fastdfs/storage #tracker 服务器的 IP 地址以及端口号 tracker_server=192.168.66.100:22122 #文件url中是否有group 名 url_have_group_name = true #存储路径 store_path0=/data/fastdfs/storage group_count = 1 #设置组的个数 #然后在末尾添加分组信息,目前只有一个分组,就只写一个 [group1] group_name=group1 storage_server_port=23000 store_path_count=1 store_path0=/data/fastdfs/storage ``` ### 配置Nginx ```sh server { listen 80; server_name localhost; location ~ /group[1-3]/M00 { alias /data/fastdfs/storage/data; ngx_fastdfs_module; } # 根目录下返回403 location = / { return 403; } # log file access_log logs/img_access.log access; } ``` ### 启动Ningx服务 ```sh # 进入sbin目录 [root@tracker nginx]# cd sbin/ # 启动服务 -c:指定配置文件 [root@tracker sbin]# ./nginx -c /usr/local/nginx/conf/nginx.conf ``` ### 查看服务启动情况 ```sh [root@tracker sbin]# ps -ef | grep nginx ``` ### 启动追踪服务与存储节点服务 ```sh [root@tracker sbin]# fdfs_trackerd /etc/fdfs/tracker.conf start [root@tracker sbin]# fdfs_storaged /etc/fdfs/storage.conf start ``` ### 上传图片测试 ```sh [root@tracker fdfs]# fdfs_upload_file /etc/fdfs/client.conf /root/xxxxx.png group1/M00/00/00/wKhyj1wrIUWAL5ASAAAfA8PiO7Y493.png ``` ### 通过浏览器远程访问 ```sh http://192.168.66.100/group1/M00/00/00/wKhyj1wrIfqAD3NFAAn1fNRE8_M976.png ```

相关推荐
麻芝汤圆1 小时前
在 IDEA 中写 Spark 程序:从入门到实践
java·大数据·hadoop·分布式·安全·spark·intellij-idea
LUCIAZZZ1 小时前
分布式链路追踪理论
java·分布式·中间件·操作系统·链路追踪
Themberfue6 小时前
Redis ⑦-set | Zset
java·开发语言·数据库·redis·sql·缓存
Doker 多克8 小时前
Django 缓存框架
python·缓存·django
群联云防护小杜9 小时前
云服务器主动防御策略与自动化防护(下)
运维·服务器·分布式·安全·自动化·音视频
TE-茶叶蛋10 小时前
秒杀压测计划 + Kafka 分区设计参考
分布式·kafka
八股文领域大手子11 小时前
深入理解缓存淘汰策略:LRU 与 LFU 算法详解及 Java 实现
java·数据库·算法·缓存·mybatis·哈希算法
青铜爱码士14 小时前
redis+lua+固定窗口实现分布式限流
redis·分布式·lua
王景程15 小时前
如何使用 Redis 缓存验证码
redis·缓存·mybatis
DO_Community15 小时前
DigitalOcean推出Valkey托管缓存服务
缓存