C/C++编程:FastDFS入门
FastDFS架构FastDFS 是一个开源的高性能分布式文件系统(DFS)。 它的主要功能包括:文件存储,文件同步和文件访问,以及高容量和负载平衡。主要解决了海量数据存储问题,特别适合以中小文件(建议范围:4KB < file_size <500MB)为载体的在线服务,比如图⽚分享和视频分享⽹站。FastDFS 系统有三个角色:跟踪服务器(Tracker Server)、存储服务器(
FastDFS架构
FastDFS是一个开源的高性能分布式文件系统(DFS)。 它的主要功能包括:文件存储,文件同步和文件访问,以及高容量和负载平衡。主要解决了海量数据存储问题,特别适合以中小文件(建议范围:4KB < file_size <500MB)为载体的在线服务,比如图⽚分享和视频分享⽹站。
FastDFS 系统有三个角色:跟踪服务器(Tracker Server)、存储服务器(Storage Server)和客户端(Client)。
(1)Tracker Server:跟踪服务器, 主要做调度工作,起到均衡的作用;
- 负责管理所有的storage server和 group,每个storage 在启动后会连接 Tracker,告知自己所属group等信息,并保存周期性心跳。 tracker根据strorage的心跳信息,建立group==>[storage server list]的映射表。
- tracker 需要管理的元信息很少,会全部存储在内存中。另外tracker 上的元信息都是由strorage汇报的信息生成的,本身不需要持久化任何数据,这样使得tracker 非常容易扩展,直接增加tracker 机器即可扩展为tracker cluster来服务,cluster里每个tracker 之间是完全对等的,所有的tracker 都接收Stroage的心跳信息,生成元数据信息来提供读写服务
(2)Storage Server:存储服务器(存储节点),主要提供容量和备份;
- 为了支持大容量,storage采用了分卷(或分组group)的组织方式。
- 存储系统由一个或多个group组成。
- ⼀个group内包含多台storage机器,数据之间互为备份(即同组内服务器上的文件是完全相同的)。同一组内的storage server之间是对等的, 文件上传、 删除等操作可以在任意一台storage server上进行
- group与group之间的文件是相互独立的,所有group的文件容量累加就是整个存储系统中的文件容量。每一个group的存储空间以group内容量最小的storage为准,所以建议 group内的多个storage尽量配置相同,以免造成存储空间的浪费。
- 可以根据应⽤的访问特性来将应⽤分配到不同的group来做负载均衡
- group内每个storage的存储依赖于本地文件系统,storage可以配置多个数据存储目录,比如有10块磁盘,分别挂载在/data/disk1-/data/disk10,则可以将这10个目录都配置为storage的数据存储目录
- storage接受到写⽂件请求时,会根据配置好的规则,选择其中⼀个存储⽬录来存储⽂件。为了避免单个⽬录下的⽂件数太多,在storage第⼀次启动时,会在每个数据存储⽬录⾥创建2级⼦⽬录,每级256个,总共65536个⽂件,新写的⽂件会以hash的⽅式被路由到其中某个⼦⽬录下,然后将⽂件数据直接作为⼀个本地⽂件存储到该⽬录中。
- 在group中增加服务器时,同步已有的文件由系统自动完成,同步完成后,系统自动将新增服务器切换到线上提供服务。当存储空间不足或即将耗尽时,可以动态添加卷。只需要增加一台或多台服务器,并将它们配置为一个新的卷,这样就扩大了存储系统的容量。
- 以group为单位组织存储能⽅便的进⾏应⽤隔离、负载均衡、副本数定制(group内storage server数量即为该group的副本数);缺点是group的容量受单机存储容量的限制,同时当group内有机器坏掉时,数据恢复只能依赖group内的其他机器,使得恢复时间很长。
(3)Client:客户端,上传/下载数据的服务器,也就是我们自己的项目部署所在的服务器。
- FastDFS向使⽤者提供基本⽂件访问接⼝,⽐如monitor、upload、download、append、delete等,以客户端库的⽅式提供给⽤户使⽤。
Tracker相当于FastDFS的大脑,不论是上传还是下载都是通过tracker来分配资源;客户端一般可以使用ngnix等静态服务器来调用或者做一部分的缓存;存储服务器内部分为卷(或者叫做组),卷于卷之间是平行的关系,可以根据资源的使用情况随时增加,卷内服务器文件相互同步备份,以达到容灾的目的。
github地址:https://github.com/happyfish100
FastDFS各功能逻辑分析
首先客户端请求Tracker服务获取到存储服务器的ip地址和端口,然后客户端根据返回的IP地址和端口号请求上传文件,存储服务器接收到请求后生产文件,并且将文件内容写入磁盘并返回给客户端file_id、路径信息、文件名等信息,客户端保存相关信息上传完毕。
upload file原理
(1)从tracher cluster选择一个tracker server
- 当集群中不止一个tracker server时,由于tracker之间是完全对等的关系,客户端在upload文件时可以任意选择一个tracker
(2)选择存储的group
- 当tracker接收到upload file的请求时,会为该文件分配一个可以存储该文件的group。支持如下选择规则:
- Round robin:所有的group间轮询
- Specified group:指定某一个确定的group
- Load balance:选择最大剩余空间的组上次文件
(3)选择storage server
- 当选定group后,tracker会在group内选择一个storage server给客户端。支持如下选择规则:
- Round robin:在group内的所有storage间轮询
- First server ordered by ip:按ip排序
- First server ordered by priority:按优先级排序(优先级在storage上配置)
(4)选择storage path
- 当分配好storage server后,客户端将向storage发送写文件请求,storage将会为文件分配一个数据存储目录。支持如下选择规则:
- Round robin:多个存储目录间轮询
- 剩余存储空间最多的优先
(5)生成Field
- 选定存储目录后,storage会为文件生成一个field,由:storage server ip、⽂件创建时间、文件大小、文件crc32和一个随机数拼接而成,然后将这个二进制串进行base64编码,转换为可打印的字符串
(6)选择两级目录
- 当选定存储目录后,storage会为文件分配一个field,每个存储目录下有两级256*256的子目录,storage会按文件field进行两次hash(猜测),路由到其中一个子目录,然后将文件以field为文件名存储到该子目录下。
(7)生成文件名
-
当文件存储到某个子目录后,即认为该文件存储成功,接下来存储服务器根据特定信息生成,文件名包含:源存储服务器IP地址、文件创 建时间戳、文件大小、随机数和文件拓展名等信息。
-
⽂件名规则:
- storage_id(ip的数值型)源storage server ID或IP地址
- timestamp(⽂件创建时间戳)
- file_size(若原始值为32位则前⾯加⼊⼀个随机值填充,最终为64位) (引⼊随机数的⽬的是防⽌⽣成重名⽂件)
- crc32(⽂件内容的检验码)
- 校验值
(8)客户端上传文件后存储服务器将文件ID返回给客户端,此文件ID用于以后访问该文件的索引信息。
- 举个例子。文件ID:group1/M00/00/00/rBEOeF5SfVeABqdKAADOcMloCIM691.jpg
- 可以看出文件索引信息包 括:组名,虚拟磁盘路径,数据两级目录,文件名。
- 组名:文件上传后所在的storage组名称,在文件上传成功后有storage服务器返回,需要客户端自行保存
- 虚拟磁盘路径:storage配置的虚拟路径,与磁盘选项store_path*对应。如果配置了store_path0则是M00, 如果配置了store_path1则是M01,以此类推
- 数据两级目录:storage服务器在每个虚拟磁盘路径下创建的两级目录
- 文件名:由存储服务器根据特定信息生成
同步机制
为什么会有同步机制:
- 同⼀组内storage server之间是对等的,⽂件上传、下载、删除等操作可以在任意⼀台storage server上进⾏;
- 值得注意的是:⽂件同步只在同组内的storage server之间进⾏,采⽤push⽅式,即源服务器同步给⽬标服务器;
具体同步过程:
- 每个存储服务器都需要定时将自身的信息上报给tracker,这些信息就包括了本地同步时间(即,同步到最新文件的时间戳)。而tracker根据各个存储服务器的上报情况,就能够知道刚刚上传的文件,在该存储组中是否已经完成了同步。
- 写文件时,客户端将文件写到group内一个storage 即认为写文件成功。storage写完文件后,会由后台将文件同步到同group内其他的storage server
- 每个storage写文件后,同时会写一份binlog,binlog里不包含文件数据,只包含文件名等元信息。这份binlog用于后台同步,storage会记录向group内其他storage同步的进度,以便重启后能接上次的进度继续同步;进度以时间戳的方式记录,所以最好能保证集群内所有的server的时钟保持同步
- storage的同步进度会作为元数据的一部分汇报到tracker上,tracker在选择storage的时候会以同步进度作为参考。比如一个group内有A、B、C三个storage,A向C同步到进度为T1(T1以前写的文件都同步到B上了),B向C同步到时间戳为T2(T2 > T1),tracker接收到这些同步进度信息时,就会进行整理,将最小的那个做为C的同步时间戳,本例中T1即为C的同步时间戳为T1(即所有T1以前写的数据都已经同步到C上了);同理,根据上述规则,tracker会为A、B生成一个同步时间戳。
download file逻辑
客户端upload file成功后,会拿到⼀个storage⽣成的⽂件名,接下来客户端根据这个⽂件名即可访问到该⽂件。
具体过程:
(1)选择tracker server
- 跟upload file⼀样,在download file时客户端可以选择任意tracker server。
(2)快递定位文件
- tracker发送download请求给某个tracker,必须带上文件名信息,
- tracker解析接收到的文件名,快速定位文件:
- 通过组名tracker能够很快的定位到客户端需要访问的存储服务器组,并将选择合适的存储服务器提供客户端访问;
- 存储服务器根据“文件存储虚拟磁盘路径”和“数据文件两级目录”可以很快定位到文件所在目录,并根据文件名找到客户端需要访问的文件。
(3)同⼀组内storage server之间是对等的,⽂件上传、下载、删除等操作可以在任意⼀台storage server上进⾏。问题是到底应该选择哪台服务器呢?
- 由于group内的文件同步时在后台是异步执行的,所以有可能出现读的时候,文件还没有同步到某些storage server上。为了尽量避免访问到这样的storage,tracker按照如下规则选择group内可读的storage。
- 该⽂件上传到的源头storage - 源头storage只要存活着,肯定包含这个⽂件,源头的地址被编码在⽂件名中。
- ⽂件创建时间戳==storage被同步到的时间戳 且(当前时间-⽂件创建时间戳) > ⽂件同步最⼤时间(如5分钟) - ⽂件创建后,认为经过最⼤同步时间后,肯定已经同步到其他storage了。
HTTP下载逻辑
FastDFS⾃带的http服务已经弃⽤,需要通过nginx + fastdfs-nginx-module的⽅式去实现下载。
学习资源
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)