FastDFS架构和原理
- FastDFS 项目地址:https://github.com/happyfish100
- FastDFS 主要功能包括:文件存储,同步和访问,基于高可用的负载均衡。FastDFS 非常适合基于文件服务的站点。
- FastDFS 有跟踪服务器(Tracker Server)、存储服务器(Storage Server)和客户端(Client)三个部分组成。主要解决海量数据存储问题。
FastDFS 架构
FastDFS 服务有三个角色:跟踪服务器、存储服务器和客户端
Tracker Server
Tracker 是 FastDFS 的协调者,负责管理所有的 storage server 和 group,每个 storage 在启动后会连接 Tracker,告知自己所属的 group 等信息,并保持周期性的心跳,tracker 根据 storage 的心跳信息,建立 group==>[storage server list]的映射表。
Tracker 需要管理的元信息很少,会全部存储在内存中;另外 tracker 上的元信息都是由 storage 汇报的信息生成的,本身不需要持久化任何数据,这样使得 tracker 非常容易扩展,直接增加 tracker 机器即可扩展为 tracker cluster 来服务,cluster 里每个 tracker 之间是完全对等的,所有的 tracker 都接受 stroage 的心跳信息,生成元数据信息来提供读写服务。
Storage Server
Storage server(后简称 storage)以组(卷,group 或 volume)为单位组织,一个 group 内包含多台 storage 机器,数据互为备份,存储空间以 group 内容量最小的 storage 为准,所以建议 group 内的多个 storage 尽量配置相同,以免造成存储空间的浪费。
以 group 为单位组织存储能方便的进行应用隔离、负载均衡、副本数定制(group 内 storage server 数量即为该 group 的副本数),比如将不同应用数据存到不同的 group 就能隔离应用数据,同时还可根据应用的访问特性来将应用分配到不同的 group 来做负载均衡;缺点是 group 的容量受单机存储容量的限制,同时当 group 内有机器坏掉时,数据恢复只能依赖 group 内地其他机器,使得恢复时间会很长。
group 内每个 storage 的存储依赖于本地文件系统,storage 可配置多个数据存储目录,比如有 10 块磁盘,分别挂载在/data/disk 1-/data/disk 10,则可将这 10 个目录都配置为 storage 的数据存储目录。
storage 接受到写文件请求时,会根据配置好的规则,选择其中一个存储目录来存储文件。为了避免单个目录下的文件数太多,在 storage 第一次启动时,会在每个数据存储目录里创建 2 级子目录,每级 256 个,总共 65536 个文件,新写的文件会以 hash 的方式被路由到其中某个子目录下,然后将文件数据直接作为一个本地文件存储到该目录中。
Client
FastDFS 向使用者提供基本文件访问接口,比如 monitor,upload,download、append、delete 等,以客户端库的方式提供给用户使用。
FastDFS 功能逻辑分析
upload file 原理
- 选择 tracker server:当集群中不止一个 tracker server 的时候,由于 tracker 之间是完全对等的关系,客户端在 upload 文件时可以任意选择一个 tracker。
- 选择存储的 group:当 tracker 接收到 upload file 的请求时,会为该文件分配一个可以存储该文件的 group,支持如下选择 group 的规则:
- Round robin:所有 group 轮询
- Specified group:指定某个确定 group
- Load balance:选择最大剩余空间的组上传文件
- 选择 storage server:当选定 group 后,tracker 会在 group 内选择选择一个 storage server 给客户端,支持如下选择 storage 的规则:
- Round robin:在 group 内的所有 storage 轮询
- First server ordered by ip:按 ip 排序
- First server ordered by priority:按优先级排序(优先级高的在上)
- 选择 storage path:当分配好 storage server 后,客户端将向 storage 发送写文件请求,storage 将会为文件分配一个数据存储目录,支持如下规则:
- Round robin:多个存储目录间轮询
- 剩余存储空间最多的优先
- 生成 Fileid:选定存储目录后,storage 会为文件生成一个 Fileid,由 storage server ip、文件创建时间、文件大小、文件 crc 32 和一个随机数拼接而成,然后将这个二进制串进行 base 64 编码,转换为可打印的字符串。
- 选择两级子目录:当选定存储目录之后,storage 会为文件分配一个 fileid,每个存储目录下有两级 256 ∗ 256 256*256 256∗256 的子目录,storage 会按文件 fileid 进行两次 hash,路由到其中一个子目录,然后将文件以 fileid 为文件名存储到子目录下。
- 生成文件名:当文件存储到某个子目录后,即认为该文件存储成功,接下来会为该文件生成一个文件名,文件名由:group、存储目录、两级子目录、fileid、文件后缀名(由客户端指定,主要用于区分文件类型)拼接而成。
- storage_id:源 storage server id 或 ip 地址;
- timestamp:文件创建时间戳;
- file_size:若原始值为 32 位则前面加入一个随机填充,最终为 64 位;
- crc 32:文件内容校验码。
- 随机数:防止文件重名
eBuDxWCb2qmAQ89yAAAAKeR1iIo162
| 4bytes | 4bytes | 8bytes |4bytes | 2bytes |
| ip | timestamp | file_size |crc32 | 校验值 |
download file 原理
跟upload file一样,在download file时客户端可以选择任意tracker server。client发送download请求给某个tracker,必须带上文件名信息,tracke从文件名中解析出文件的group、大小、创建时间等信息,然后为该请求选择一个storage用来服务读请求。由于group内的文件同步时在后台异步进行的,所以有可能出现在读到时候,文件还没有同步到某些storage server上,为了尽量避免访问到这样的storage,tracker按照如下规则选择group内可读的storage。
- 该文件上传到的源头 storage-源头 storage 只要存活,肯定包含这个文件,源头的地址被编码在文件名中。
- 文件创建时间戳=storage 被同步到时间戳且(当前时间-文件创建时间戳) > 文件同步最大时间-文件创建后,认为经过最大同步时间后,肯定已经同步到其他 storage 了。
- 文件创建时间<storage 被同步到的时间戳,同步时间戳之前的文件确定已经同步了。
- (当前文件-文件创建时间)>同步延迟阈值。经过同步延迟阈值时间,认为文件肯定同步了。
Http 下载原理
nginx+fastdfs-nginx-module