fastDFS文件服务器(一):原理篇

传统文件存储问题

单机存储不了,就将数据分散存储到多台机器,并通过在软件层做封装提供统一的存储接口,使得存储服务的使用者不需要关心数据是如何存储、存储在哪里的。

以磁盘为存储介质的单机文件系统(如ext4、xfs等),文件都是以目录树结构来组织的,当文件数很多时,目录内的文件数会很多、目录层次也会变深,使得路径查找是非常影响性能的,一次路径名查找可能需要多次磁盘IO。

目前分布式文件存储系统的解决方案

TFS、FASTDFS、HDFS都是通过将数据分布到多个存储节点来解决问题
1、通过将多个文件打包存储到大文件(block)以及扁平化的目录结构来解决问题
2、通过block多副本以及按block复制的方式来解决问题。
3、block通常64MB大小,block内部存储的每个文件由一个fileid标识。

步骤一

将索引文件不持久化存储,在内存里组织为hash表;存储时将文件追加到block尾部后,将文件在block内部的offset以及文件size信息,插入到hash表中;访问该文件时,先根据文件的id在hash表中定位文件的offset和size,然后在block对应位置读取文件数据,由于hash表是全内存化的,访问文件只需一次IO。

这种方案的优点在于,每次存储文件时,只需要一次IO操作,不会出现索引与block实际文件数据不一致大情况;缺点在于,索引只存在于内存,当服务重启时,index信息需要根据block的数据来重建,,这就要求文件在block中存储时,必须存储一些额外的头信息,使得block的文件具有自描述能力,在每次启动时,通过扫描block数据来生成index。

以2T磁盘、64MB block为例,磁盘上会有约30000个block;假设扫描一个block需要1s,那么启动时间约为500min * 0.8(磁盘使用率80%)= 400min,显然,每次启动时扫描block来生成index的开销是不可接受的。

步骤二

在步骤一的基础上,每个block对应一个index文件,写文件时先将文件数据追加到block的尾部,然后将文件的index插入到内存hash表,最后将文件的index追加到index文件;在存储服务重启时,每个block根据其index文件来快速建立内存hash表。

步骤二解决了索引重建的问题,但其每次写文件需要两次IO,写文件的延时就高了。为了降低写的延时,facebook在开源贡献了一种折中的方案。文件写入时,往block追加文件数据时同步刷盘,然后将记录插入到内存hash表,接下来追加index记录时,发送完追加请求就认为写文件成功,即index并不立即刷盘,这样写的延时缩短到一次IO。

文件index异步追加,可能导致一个问题,文件在block里存在,但在index文件里没有这个文件的记录,在根据index文件重建内存hash表时,hash表就是不完整的,导致部分文件访问不到。facebook通过在重建时,从block尾部开始扫描,找出所有可能缺失index的文件,并生成index追加到index文件。

步骤三

步骤二中index的数据实际上是存在两份的,一份是内存hash表里的,一份是index文件里的,因为linux的页缓存机制,文件里的index也是可能cache在内存里,所以步骤二对内存的利用不是最优的,可以考虑将index文件和index内存hash表合二为一,将index文件本身以hash表的方式组织,直接使用mmap将index文件映射到内存。

通过将index文件和内存hash表合二为一,操作内存index即为操作index文件,管理index会方便不少。为了解决hash冲突问题,每个index条目需要额外增加一个next字段用于连接冲突链。

这种还存在hash扩展的问题,当block内存储的小文件数量很多时,按照预估的hash桶数(预估值通常不会太大,太大会有很多空间浪费),可能会导致冲突链很长,这时要提高hash查找的效率就必须扩展桶的数量,如果使用步骤一,扩展只会导致额外的内存拷贝,而在这个步骤三里,则会导致整个index文件重写,会产生IO操作。

fastDFS分布式设计原理

FastDFS是一个开源的分布式文件系统,由tracker serverstorage server和client三个部分组成,主要解决了海量数据存储问题,特别适合以中小文件(建议范围:4KB < file_size <500MB)为载体。

1、Storage server

Storage server(后简称storage)以组(卷,group)为单位,一个group内包含多台storage机器,数据互为备份,存储空间以group内容量最小的storage为准,所以建议group内的多个storage尽量配置相同,以免造成存储空间的浪费。

以group为单位存储能方便的进行应用隔离、负载均衡、副本数定制,比如将不同应用数据存到不同的group就能隔离应用数据,同时还可根据应用的访问特性来将应用分配到不同的group来做负载均衡;缺点是group的容量受单机存储容量的限制,同时当group内有机器坏掉时,数据恢复只能依赖group内地其他机器,使得恢复时间会很长。

group内每个storage的存储依赖于本地文件系统,storage可配置多个数据存储目录,比如有10块磁盘,分别挂载在/data/disk1-/data/disk10,则可将这10个目录都配置为storage的数据存储目录。

storage接受到写文件请求时,会根据配置好的规则,选择其中一个存储目录来存储文件。为了避免单个目录下的文件数太多,在storage第一次启动时,会在每个数据存储目录里创建2级子目录,每级256个,总共65536个文件,新写的文件会以hash的方式被路由到其中某个子目录下,然后将文件数据直接作为一个本地文件存储到该目录中。

2、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的心跳信息,生成元数据信息来提供读写服务。

3、上传原理

上传流程图

4、同步原理

写文件时,客户端将文件写至group内一个storage server即认为写文件成功,storage server写完文件后,会由后台线程将文件同步至同group内其他的storage server。每个storage写文件后,同时会写一份binlog,binlog里不包含文件数据,只包含文件名等元信息,这份binlog用于后台同步,storage会记录向group内其他storage同步的进度,以便重启后能接上次的进度继续同步;进度以时间戳的方式进行记录,所以最好能保证集群内所有server的时钟保持同步。

storage的同步进度会作为元数据的一部分汇报到tracker上,tracke在选择读storage的时候会以同步进度作为参考。

比如一个group内有A、B、C三个storage server,A向C同步到进度为T1 (T1以前写的文件都已经同步到B上了),B向C同步到时间戳为T2(T2 > T1),tracker接收到这些同步进度信息时,就会进行整理,将最小的那个做为C的同步时间戳。

5、下载原理

下载流程图

6、小文件合并存储

将小文件合并存储主要解决如下几个问题:

  1. 本地文件系统inode数量有限,从而存储的小文件数量也就受到限制。

  2. 多级目录+目录里很多文件,导致访问文件的开销很大(可能导致很多次IO)

  3. 按小文件存储,备份与恢复的效率低

FastDFS在新版本中,可将多个小文件存储到一个大的文件(trunk file),为了支持这个机制,FastDFS生成的文件fileid需要额外增加16个字节,每个trunk file由一个id唯一标识,trunk file由group内的trunk server负责创建(trunk server是tracker选出来的),并同步到group内其他的storage,文件存储合并存储到trunk file后,根据其offset就能从trunk file读取到文件。文件在trunk file内的offset编码到文件名,决定了其在trunk file内的位置是不能更改的,也就不能通过compact的方式回收trunk file内删除文件的空间。但当trunk file内有文件删除时,其删除的空间是可以被复用的,比如一个100KB的文件被删除,接下来存储一个99KB的文件就可以直接复用这片删除的存储空间。

7、HTTP访问支持

FastDFS的tracker和storage都内置了http协议的支持,客户端可以通过http协议来下载文件,tracker在接收到请求时,通过http的redirect机制将请求重定向至文件所在的storage上;除了内置的http协议外,FastDFS还提供了通过apache或nginx扩展模块下载文件的支持。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容