1 FastDFS原理

1.1 分布式存储

1.1.1 单机服务器

在同一台服务器上保存所有项目文件,不同类型的文件存放在不同的子目录下。如下图所示:

应用服务器
app
bin
include
source
lib
resource
docs
images
audio
video

在这样的项目文件组织结构中,包含include目录下的头文件,编译source目录下的源文件,链接lib目录下的库文件,在bin目录下生成二进制可执行文件。运行bin目录下的可执行文件,产生一到多个应用程序进程实例,它们会根据用户的需要,从resource目录下获取,诸如图像、音频、视频等,不同类型的多媒体资源。docs目录用于存放与项目有关的各种文档。

优点

  1. 实现简单:在一台计算机上,直接利用文件系统划分不同类型的文件;

  2. 访问方便:应用程序无需借助任何复杂技术,就能直接访问资源目录下的多媒体数据。

缺点

  1. 不易管理:源代码、可执行代码、第三方代码和资源媒体,紧密耦合在同一台计算机的同一个文件系统中。文件越多,分类越细,目录结构越复杂,文件存放越混乱;

  2. 性能不佳:同时为多个客户机提供服务的多个进程或线程,同时访问同一台计算机同一个文件系统中的资源文件,会导致服务器整体性能下降,延长响应时间,影响用户体验。

1.1.2 独立服务器

随着公司业务的不断发展,将代码和资源放在同一台服务器上的弊端将日益凸显,为此考虑引入独立的资源服务器专门负责存储和管理包括图像、音频、视频等在内的多媒体资源。具体操作过程包括:

如下图所示:

资源服务器
资源文件
资源文件
URL
FTP/SSH
resource
images
audio
video
Ngnix/Apache
上传客户机
应用服务器
业务客户机

优点

  1. 对图像、音频、视频等多媒体资源的访问,因其涉及到频繁的系统上下文切换和大量的磁盘I/O操作,通常都会十分消耗系统资源。将其分离出来,运行在独立的资源服务器上,势必极大地减轻应用服务器的压力,使之更加专注于发挥面向业务逻辑的动态处理效能;

  2. 将有关数据存储的工作,交由独立的资源服务器专门负责,便于对数据进行扩容、容灾以及迁移;

  3. 独立的资源服务器可以借助于负载均衡、数据缓存等技术手段,进一步提高对资源的访问效率,同时为日后迁移到CDN做好准备。

缺点

  1. 只靠一台资源服务器容易形成性能瓶颈,其容灾和垂直扩展性也稍差。

1.1.3 分布式存储

随着业务的持续发展,对应用系统的高响应性和高可用性的要求会越来越高。为了解决单台资源服务器性能有限、容灾和垂直扩展性差等问题,考虑引入分布式存储。分布式存储由以下三部分组成:

如下图所示:

分布式存储
存储系统
资源文件
资源文件
URL
仲裁系统
容灾系统
存储主机
存储主机
存储主机
存储主机
上传客户机
应用服务器
业务客户机

优点

  1. 高响应性:通过在多台存储主机间均衡负载,消除了由单台资源服务器形成的性能瓶颈,缩短了对应用服务器的响应时间;

  2. 高可用性:多台存储主机互为备份,任何一台主机出现故障,都不至影响整个系统的平稳运行;

  3. 高扩展性:可根据业务需要,灵活增减存储主机的数量,无需中断系统运行。

缺点

  1. 系统复杂度稍高,需要更多的服务器。

1.2 FastDFS

1.2.1 系统简介

FastDFS是一款开源轻量级分布式文件系统。它解决了大数据量的存储和负载均衡等问题,特别适合以介于4K到500M字节之间的中小文件为载体的在线服务,如相册、音乐、视频网站等。现有的很多基于FastDFS开发的业务系统,正在向用户提供诸如网盘、社区、广告和应用下载等存储服务。

FastDFS采用纯粹C语言实现,支持Linux、FreeBSD等类UNIX操作系统,类似于GFS (Google File System,谷歌文件系统),并非通用文件系统,只能通过专有API访问,目前提供了面向C、Java和PHP的编程接口,专为互联网应用量身定做,解决海量文件存储问题,追求高性能和高扩展性。FastDFS可被视为一种面向文件的键——值对存储系统,称其为分布式文件存储服务更为恰当。

FastDFS具有如下特性:

1.2.2 基本概念

完整的FastDFS系统包括跟踪服务器(Tracker)、存储服务器(Storage)和客户机(Client)三个重要角色,以及组(Group)、元数据(Meta Data)等逻辑对象。如下图所示:

Clients
Storage Cluster
Tracker Cluster
Group
Client
C...
G...
Storage
S...
Tracker
T...

1.2.2.1 跟踪服务器(Tracker)

1.2.2.2 存储服务器(Storage)

1.2.2.3 客户机(Client)

1.2.2.4 组(Group)

1.2.2.5 元数据(Meta Data)

1.2.3 文件上传

完整的文件上传流程如下图所示:

StorageTrackerClientStorageTrackerClient1. 定时通告状态信息2. 请求上传文件3. 查询可用的Storage4. 响应可用Storage的IP地址和端口号5. 上传文件的内容数据和元数据6. 生成文件标识7. 将文件的内容数据保存到文件系统的特定目录下8. 返回文件的访问路径9. 保存文件的访问路径
  1. 每台存储服务器通过周期性心跳向跟踪服务器定时通告其自身状态,后者负责汇总和维护这些信息;

  2. 客户机向跟踪服务器发起有关上传文件的请求;

  3. 跟踪服务器在其维护的有关存储服务器的信息中查询可用的存储服务器;

  4. 跟踪服务器向发起上传请求的客户机响应以可用存储服务器的IP地址和端口号;

  5. 客户机根据接收到的IP地址和端口号向特定存储服务器上传文件的内容数据和元数据;

  6. 存储服务器根据接收到的文件数据生成唯一的文件标识;

  7. 存储服务器将接收到的文件内容数据保存到文件系统的特定目录下;

  8. 存储服务器向客户机返回文件的访问路径;

  9. 客户机保存从存储服务器接收到的文件访问路径,以备下载之需。

在文件上传的过程中会涉及到以下内部处理:

1.2.3.1 选择跟踪服务器

当跟踪服务器集群中不止一台跟踪服务器时,由于各跟踪服务器之间是完全对等的关系,客户机在上传文件时可以任意选择一台跟踪服务器,发起有关上传文件的请求。

Tracker Cluster
Tracker1
Tracker2
Tracker3
Tracker4
Client

1.2.3.2 选择组

当跟踪服务器接收到来自客户机的上传文件请求时,会为该文件分配一个用于存储的组。FastDFS支持如下选组规则:

Storage Cluster
Group1
Group2
Group3
Group4
Tracker1

1.2.3.3 选择存储服务器

在跟踪服务器为请求上传文件的客户机选定组以后,将在该组内依如下规则为其选择一台存储服务器用于存储文件:

Group1
Storage1
Storage2
Storage3
Storage4
Tracker1

1.2.3.4 选择存储目录

跟踪服务器最终将选定的存储服务器的IP地址和端口号,以响应报文的形式发回给请求上传文件的客户机。后者根据接收到的IP地址和端口号向该存储服务器上传文件的内容数据和元数据。存储服务器需要为接收到的文件内容数据选择一个特定的存储目录用于保存文件。FastDFS支持如下存储目录选择规则:

Storage1
data
disk1
disk2
disk10
....

1.2.3.5 生成文件标识

在选定存储目录之后,存储服务器会将其IP地址、文件创建时间、文件大小、文件内容的循环冗余校验码(CRC32)和一个随机数拼接在一起,做Base64编码,得到一个可显示字符串,即文件标识(File ID)。

可显示字符串
二进制字节序列
Base64
文件标识
存储服务器IP地址
文件创建时间
文件大小
文件内容的循环冗余校验码
随机数

每个存储目录下有两级子目录,每级256个,共65536个子目录。存储服务器对文件标识做两次散列,路由到其中某个特定子目录下,将文件以文件标识为文件名保存在该子目录下。

存储目录
第一级子目录
第二级子目录
disk1
00
wKgADl7PZmWAWDR0A3_8qu7Bxj0478.mp4
00
01
....
FF
01
....
FF

1.2.3.6 生成访问路径

当文件被保存到某个子目录后,即可认为该文件已经存储成功,接下来将为该文件生成一个访问路径。文件的访问路径由组、存储目录、两级子目录、文件标识和表示文件类型的后缀组成。如:

而后客户机将通过类似下面的URL下载该文件:

其中192.168.0.11、192.168.0.12、192.168.0.13和192.168.0.14分别为Tracker1、Tracker2、Tracker3和Tracker4的IP地址,8080为每台跟踪服务器的Web服务端口。

URL
访问路径
:////
:
//
//
//
//
//
.
协议
跟踪服务器的域名或IP地址
跟踪服务器的Web服务端口
存储目录
第一级子目录
第二级子目录
文件标识
后缀

1.2.4 文件下载

完整的文件下载流程如下图所示:

StorageTrackerClientStorageTrackerClient1. 定时通告状态信息2. 请求下载文件3. 查询可用的Storage4. 响应可用Storage的IP地址和端口号5. 提交文件的存储路径6. 查找文件7. 返回文件的内容数据8. 保存文件的内容数据
  1. 每台存储服务器通过周期性心跳向跟踪服务器定时通告其自身状态,后者负责汇总和维护这些信息;

  2. 客户机向跟踪服务器发起有关下载文件的请求,其中包括组和文件标识;

  3. 跟踪服务器根据组和文件标识中的存储服务器IP地址、文件创建时间、文件大小等信息,查询可用的存储服务器;

  4. 跟踪服务器向发起下载请求的客户机响应以可用存储服务器的IP地址和端口号;

  5. 客户机根据接收到的IP地址和端口号向特定存储服务器提交文件的存储路径,其中包括文件的存储目录、两级子目录、文件标识和表示文件类型的后缀;

  6. 存储服务器根据接收到的文件存储路径,在其文件系统中查找该文件;

  7. 存储服务器向客户机返回文件的内容数据;

  8. 客户机将从存储服务器接收到的文件内容数据保存在本地,以备后续之需。

由于组内各存储服务器间的文件同步是于后台异步进行的,因此当客户机请求下载某文件时,该文件可能尚未被同步到组内的每一台存储服务器上。为了避免恰好选中某台尚未取得同步的存储服务器,跟踪服务器需依如下规则选择特定组内的可用存储服务器:

  1. 从文件标识中提取存储服务器的IP地址,该地址所标识的存储服务器被称为源存储服务器,其中肯定存有被请求下载文件的完整内容。因此源存储服务器一定是可用存储服务器;

  2. 从文件标识中提取文件的创建时间,与存储服务器开始同步该文件的时间进行比较:

    • 创建时间等于同步时间:这说明几乎在创建该文件的同时就开始同步了,但并不能保证同步已经完成,因此还要进一步检查当前时间与创建时间的差是否大于最大同步过程时间,即只有经过足够长的时间,才能确定文件同步完了;

    • 创建时间小于同步时间:存储服务器上的文件是被顺序同步的,即同步完一个文件再同步下一个文件,因此那些在该文件被同步之前就被同步的文件,此时肯定已经同步完了。

  3. 如果当前时间与从文件标识中提取的文件创建时间之间的间隔足够大,比如大于最大同步延迟时间,那么可以认为该文件已经同步完了。

1.2.5 时间同步

1.2.5.1 同步进度

在客户机成功上传一个文件后,该文件即被保存在某个组内的某台存储服务器上。运行在该存储服务上的同步线程会按照文件时间戳的先后顺序,将这些文件同步到组内其它存储服务器上:

Group1
Storage1
Storage2
Storage3
Storage4
1:00
2:00
3:00
A(1:00)
A
A
A
B(2:00)
B
B
C(3:00)
C
D(4:00)

如图所示,组Group1中的存储服务器Storage1接收到不同客户机上传的文件A、B、C和D,其时间戳分别为1:00、2:00、3:00和4:00。经过一段时间后,文件A被同步到组内另外三台存储服务器Storage2、Storage3和Storage4上;文件B被同步到Storage2和Storage3上;文件C仅被同步到Storage2上;文件D则尚未被同步到任何存储服务器上。这时Storage1对Storage2的同步进度为文件C的时间戳3:00,Storage1对Storage3的同步进度为文件B的时间戳2:00,而Storage1对Storage4的同步进度则为文件A的时间戳1:00。这三个同步进度都保存在Storage1的磁盘文件中。这时若Storage1宕机,待其重启后,将查找时间戳分别晚于这三个同步进度的文件向其对应的存储服务器做同步。

由此可见,若源存储服务器对目标存储服务器的同步进度为T,则说明在源存储服务器上所有时间戳不晚于T的文件都已被同步到目标存储服务器上。

1.2.5.2 同步时间戳

每台存储服务器启动后,都会与跟踪服务器建立连接,并通过周期性心跳向跟踪服务器定时通告其自身状态,其中就包括该存储服务器对其它存储服务器的同步进度。跟踪服务器将根据这些同步进度为每台存储服务器生成一个同步时间戳,所有时间戳不晚于同步时间戳的文件肯定已被同步到该存储服务器上。

如图所示,组Group1中的存储服务器Storage1、Storage2、Storage3和Storage4。其中:

取三个同步进度T1、T2和T3中的最小值T1作为存储服务器Storage4的同步时间戳。在其它存储服务器上如果有某个文件的时间戳不晚于Storage4的同步时间戳(T1),则可以断定该文件此时肯定已经被同步到Storage4上了,如文件A、E和I,而对于时间戳晚于Storage4同步时间戳(T1)的文件,则可能已被同步,如文件F、J和K,也可能尚未同步,如文件B、C、D、G、H和L。使用类似的方法,可以得到每台存储服务器的同步时间戳。

1.2.6 访问路径和文件标识

1.2.6.1 访问路径

为了下载文件,客户机需要向跟踪服务器提交被下载文件的访问路径,该路径是在文件上传过程中由存储服务器生成并返回给客户机的。文件的访问路径由组、存储目录或虚拟路径、两级子目录、文件标识和表示文件类型的后缀组成。如下图所示:

注:虚拟路径本质上是个指向存储目录的符号链接。

1.2.6.2 文件标识

文件标识是文件名中类似“wKgADl7PZmWAWDR0A3_8qu7Bxj0478”的字符串。事实上它是一串二进制字节序列的Base64编码。该序列由源存储服务器IP地址、文件创建时间、文件大小、文件内容的循环冗余校验码(CRC32)和一个随机数组成。如下图所示:

1.2.6.3 快速定位

当客户机需要下载文件时,首先将包含访问路径的下载请求发送给跟踪服务器。访问路径中携带了组和文件标识等信息。跟踪服务器根据组和文件标识中的源存储服务器IP地址、文件创建时间、文件大小等信息,查询可用的存储服务器,并返回给客户机。客户机再次将包含访问路径的下载请求发送给上一步得到的可用存储服务器,后者根据访问路径中的存储目录或虚拟路径、两级子目录、文件标识和类型后缀定位到具体文件,读取其内容,返回给客户机。如下图所示:

访问路径
存储服务器信息
访问路径
文件内容
下载客户机
跟踪服务器
存储服务器

达内集团◇C++/嵌入式◇闵卫