分布式文件系统及FastDFS

1、前言

今天来谈谈分布式文件系统,侧重点是文件系统,分布式稍微带一下。然后聊下我用的FastDFS的例子。

2、从小需求开始

我的博客的编辑器用的是markdown,它内嵌了一个文件上传功能,不过后端文件管理要自己的写。
最开始直接用SpringMVC接收上传文件,直接扔服务器新建的upload文件夹下。但问题很快就出现了,上传同名文件会冲突,顺手加个时间戳好像可以解决问题,但我总感觉重复文件最后只存一次才是最好的,但靠文件名是没法判断重复的,加上大小,类型也不够,查了不少资料,考虑到自己写没足够的精力,最后决定用现成的FastDFS,学习别人是怎么做的。
由上,我们有这么几个问题:

  1. 文件存哪?
  2. 怎么存?
  3. 如何去重?

...

带着这几个问题来看看文件系统的设计。

3、文件系统

3.1 什么是文件系统。

如果是windows,按win+E打开资源管理器,资源指是什么,是文件,文件管理器,也就是文件系统。在Linux,Mac,Android,iOS之上,所有应用都是由文件系统所管理。操作系统中负责管理和存储文件信息的软件机构称为文件系统。

3.2 文件系统的分类

文件系统从架构上可以分为两类:
1.本地文件系统
linux的ext3,ext4 windows的FAT32 NTFS ..
如下是window下格式化硬盘时可以选择的文件系统。注意下其中有个参数分配单元大小,稍后讨论。

2.分布式文件系统
分布式文件又可以分为两种,

一是通用分布式文件系统
将windows或linux多台机器进分布式架构便是一个通用分布式文件系统了,因为通用,使用起来很方便,但性能就差点。应用端可以mount(挂载)使用。典型代表:lustre、MooseFS.

另外一个便是专用分布式文件系统了,基本都是基于GFS的思想,,文件上传后不能修改。不能mount使用,需要使用专有API对文件进行访问,也可称作分布式文件存储服务。典型代表:GFS、FastDFS、HDFS、TFS。

3.2 文件的存储

文件系统最基本的功能便是存储了,存储方式分为两种:

1.独立文件形式存储
即以N级目录+文件的方式存储文件,win,linux,mac..都是这种方式,这种方式查询很快,根据路径自然就可以找到文件。

但是,在前面的图片中谈到了一个参数分配单元大小,值是4K。我们看几个文件的属性:


其中的大小是文件的大小,但占用空间却比实际大小大,而且正好是4k的倍数,没错文件系统中文件大小的单位是固定的,又称为文件簇,这个指文件分配的最小空间,这个值设小可以节省空间但访问速度会变慢,反之则浪费空间,但可以加快访问速度。有人会建议如果硬盘空间足够可在格式化硬盘时选择分配单元大小为64k,从而提高系统性能。

如果都是大文件,浪费的空间可以不计,但如果都是2k的小文件呢,100w这种小文件实际大小不到2g,但占用空间近4g,一般空间被浪费掉了。所以有了另一种存储方式。

2.块存储
如果将100w小文件写入压缩包,里面虽然是100w文件,但在系统中其实是一个压缩文件,这样它所占用的空间是实际大小了,如果是压缩存储还会更小。这种方式我们称之为块存储。

这两者各有优劣,块存储节省空间,但想访问其中一个就比较麻烦,文件存储访问很快,但海量小文件情况下空间浪费就大了。

3.二者的应用场景
分布式文件系统FastDFS使用的是文件存储,应用于分布式访问,建议用于>4k的文件访问便是这个道理;

但另外一个HDFS使用的是块存储,它所应用的场景是分布式计算,其实需要的是一次性加载数以百万的文件到MapReduce服务器中运算,如果一个个下载肯定不如直接一个压缩包过来。

3.2 文件的去重

一般我们使用的操作系统中,只会限制重复文件名,并不会确定两个文件的数据是否一样。
但当文件开始多起来,比如百度网盘,现在一个蓝光电影能有十几g,如果网友每人传一份,百来个人就能占1t,虽然硬盘不值钱,但亿万级的文件堆起来也开销不少,如果能去重,那只用维持一份数据就好了。

文件去重,也是需要找到一个唯一标识来定位文件。hash是一个比较好的选择。
Hash 即散列,当数据足够散,一个点只有一份数据,不出现hash冲突,这不就是唯一了。
hash值可以用自己定义计算,但更通常的做法是用MD5,SHA1这样成熟的hash算法。
MD5之类不仅仅是用来加密,也早就大量用于文件防伪,当然hash的碰撞仍然存在,经过精心设计,完全可以伪造出MD5相同,但数据不同文件,从而带来安全问题,毕竟这个文件如果是手机银行呢。

3.4 秒传的秘密

百度网盘秒传原理

四、分布式文件系统-FastDFS

文件存储问题解决了,下面就是分布式的东西的。
关于分布式的架构思路请参考下我的另外一篇文章,这里就不累述了。

以下是FastDFS架构图

Tracker:负载均衡服务器。
Storage:存储服务器。
这里简单的介绍下它的一些流程。

4.1 上传下载流程

  • 上传
  • client询问tracker上传到的storage;
  • tracker返回一台可用的storage;
  • client直接和storage通信完成文件上传,storage返回文件ID。
  • 下载
  • client询问tracker可以下载指定文件的storage,参数为文件ID(组名和文件名);
  • tracker返回一台可用的storage;
  • client直接和storage通信完成文件下载。

上传文件时,文件ID由storage server生成并返回给client
文件ID包含了组名和文件名,storage server可以直接根据该文件名定位到文件
一个文件ID示例:

4.2 同步机制

采用binlog文件记录文件上传、删除等操作,根据binlog进行文件同步;

storage生成的文件名中,包含源头storage IP地址和文件创建时间戳;
源头storage定时向tracker报告同步情况,包括向目标服务器同步到的文件时间戳;
tracker收到storage的同步报告后,找出该组内每台storage被同步到的时间戳(取最小值),
作为storage属性保存到内存中;

client询问tracker有哪些storage可以下载指定文件时,tracker返回满足如下四个条件之一的storage:
1 (当前时间 -文件创建时间戳) > 同步延迟阀值(如一天);
2 文件创建时间戳 < Storage被同步到的时间戳;
3 文件创建时间戳==Storage被同步到的时间戳 且(当前时间 -文件创建时间戳) > 文件同步最大时间(如5分钟);
4 该文件上传到的源头storage。

由于文件不要求强一致性,所以同步方案要求不高,完全没必要使用paxos之类的一致性算法,这是与分布式缓存,数据库等差别较大的地方

4.3 FastDFS去重机制

去重机制也就是hash了,一个是自己实现的hash,另外一个是MD5。
Hash: 4*32位hash code
MD5:

需安装FastDHT(分布式哈希系统 ):使用 Berkeley DB 做数据存储,使用 libevent 做网络IO处理,提供 Java 版的客户端接口包。适合用来存储用户在线、会话等小数据量信息。
通过hash->文件路径来标识文件,后面上传的文件,如果已经存在相同内容的文件,则采用符号连接的方式,指向原始文件。

缺陷:我们看到的是FastDFS采用服务端去重的机制,相比网盘的秒传机制效率低。所以我的网站目前没有使用这一机制,更考虑做个网盘类似的插件,本地去重,这个排后吧。以后可以玩玩。

五 扩展参考

Comments
Write a Comment