前言:FastDFS 是一个分布式文件存储系统,主要用于存储和管理大规模的文件数据,如图片、视频、文档等,是淘宝前架构师为了存储图片用C语言开发出来的系统。
服务端有两个组件 Tracker Server 与 Storage Server ,对应两个角色:
Tracker: 管理和调度集群,tracker 也可实现集群。每 tracker 节点地位平等。收集 Storage 集群的状态。
Storage: 实际保存文件,,Storage 分为多个组,每个组之间保存的文件是不同的。每个组内部可以有多个成员,组内成员保存的内容是一样的,组成员的地位是一致的,无主从的概念。
工作原理过程:
客户端 Client 请求 Tracker server 进行文件上传、下载,通过 Tracker server 调度最终由 Storage server 完成文上传和下载。
详细而言即,Storage 会定时向 Tracker 上报状态信息,当 Tracker 接到 Client 上传或下载 文件请求,Tracker 查询可用 Storage 并返回对应可用的IP和端口,接下来 Client 才真正地上传或下载文件到 Storage 并会带回一些文件信息(文件名、文件ID)返回 Client。
设计功能:
(1)组内备份,Storager同组内会做备份操作(实时数据同步)
(2)横向扩容(线性扩容),存在这样一种场景:当前太多人访问 Storager1-1 服务器下载,那此时再往里存文件就会导致性能下降,那么就会找到 Storager1-2 里存文件(读写分离的感觉),同时他们的数据是实时同步的,就能达到目的。如果都存满了,就横向扩容到Storager2-1。
(3)负载均衡能力。
查询方式:
FastDFS 通过文件名或文件 ID 来定位和访问文件。它不支持复杂的查询操作。
具有特性:
- 高性能:FastDFS采用了多级缓存、分布式存储等技术,具有较高的I/O性能。
- 高可用:FastDFS支持文件副本,可以自动进行故障转移,确保数据的可靠性。
- 高并发:FastDFS可以同时处理大量的文件上传、下载请求,适用于高并发场景。
- 易扩展:FastDFS可以通过添加存储服务器来扩展存储容量,支持在线扩容。
适用场景:
FastDFS 适用于大数据处理、云存储、内容分发等场景,特别是对大文件存储和高并发访问有要求的场景。
以下给出Django配置示例:
(1)安装 FastDFS 的 Python 客户端库(如 fdfs_client-py)
pip install fdfs_client-py
(2)Django中FastDFS配置相关环境变量与配置默认的文件存储后端:
# django⽂件存储
DEFAULT_FILE_STORAGE = 'xxx.FastDFSStorage' # 替换为实际的存储后端类路径
# FastDFS
FDFS_BASE_URL = 'http://系统IP:对应开放端口/' # FastDFS 访问地址(注意结尾的斜杠)
FDFS_CLIENT_CONF = 'xxx/client.conf' # FastDFS 客户端配置文件路径
(3)创建一个 Django 存储后端类,用于将文件上传到 FastDFS,比如:
from django.core.files.storage import Storage
from django.conf import settings
from fdfs_client.client import Fdfs_client
class FDFSStorage(Storage):
def __init__(self, client_conf=None, base_url=None):
if client_conf is None:
client_conf = settings.FDFS_CLIENT_CONF
if base_url is None:
base_url = settings.FDFS_URL
self.client_conf = client_conf
self.base_url = base_url
def _open(self, name, mode='rb'):
pass
def _save(self, name, content):
# 创建 FastDFS 客户端
client = Fdfs_client(self.client_conf)
# 上传文件
result = client.upload_by_buffer(content.read())
# 检查上传结果
if result.get('Status') != 'Upload successed.':
raise Exception('Upload file to FastDFS failed')
# 返回文件名
return result.get('Remote file_id')
def exists(self, name):
return False
def url(self, name):
return self.base_url + name