理解小文件存储 haystack

秋收图

也许生活在这钢筋混泥土之中,早已淡了季节轮回的感触,忽视了做为大自然的有机体,新陈代谢,生生不息的一面。秋天短暂,却是收获喜悦的季节,幸福四溢,风乍起,那麦浪的金黄。


与分布式fs擦肩而过

2013年开始筹划数据库的拆分,2C的分类信息网站时间序特征很明显。每天都有对历史数据进行归档,不断的瘦身,典型按时间 "horizontal sharding"。随着业务增长和变化,热数据已有几百GB,特别是开放免费端口后,短时间数据暴增,例如二手房源表,单表100G,按主键的查询也非常慢,系统极不稳定。

由于系统设计问题,MySQL 直接存储详情页描述部分的 HTML 代码。经过分析,描述 TEXT字段平均 6KB 左右,100G的单表,贴子属性数据只有20G,其它均为描述 TEXT 字段,决定拆字段,也就是所谓的 "vertical sharding"。拆出的 TEXT 字段存储有两个选择,MySQL 或是分布式文件系统。对市面上一些系统做调研后,没有运维经验,出于稳定性和非侵入考虑,选择扔然存储在 MySQL 中。后来做 Automan SQL 自动上线,支持批量文件上传,保存在本机文件系统中,一直没有改成存储分布式文件系统中,很可惜,擦肩而过。

上周看毛剑在写基于 haystack 的文件系统,正好重温一遍。

脸书老的图片架构

图片访问流程

上图是标准的图片访问流程,用户上传图片,Web Server 直接存储到后端存储中,并将图片 Url 保存到数据库中,例如 MySQL等。Url 类似如下格式:

http://<Machine ID>/FILE/PATH

当请求发出后,Web Server 从 MySQL 中取出图片 Url 信息,包裹一层 CDN 信息,扔到用户的浏览器页面。由用户浏览器按照包裹后的 Url 渲染页面,包裹的格式可能如下:

http://<CDN>/<TAG>/<Machine ID>/FILE/PATH

CDN 处理请求,如果图片不存在,那么根据协议剥离出真实图片 Url,去源站请求冲 Cache,这就是人们常说的 CDN 回源,监控回源率来不断优化业务。

NFS-Based Design

自然地,脸书老架构也是将图片保存到类 POSIX 文件系统中,商业共享存储 + NFS 挂载模式。这个模式支持脸书的飞速发展,比较像05年阿里的IOE。后来这个架构遇到了瓶颈:

1. 脸书图片四个尺寸,随着量越来越大,长尾理论突显,CDN 缓存这些长尾成本太高。

2. 类 POSIX 存储方式,为获取文件,访问 metadata 产生很多 IO 。比如说权限这些属性信息就是不必要的,如果 metadata 全部缓存在内存中,成本太高。

脸书haystack架构

Haystack 是脸书在2012年发布的论文《Finding a needle in Haystack: Facebook’s photo storage》,详细描述了他们的图片存储架构更迭。那么 haystack 就是要解决这些问题,有四个设计目标:

1. High throughtput and low latency. 和数据库 OLTP 业务类似,要求高吞吐和低延迟,一方面热门图片缓存到 CDN 中,另外一方面减少存储磁盘 IO 次数,将 metadata 存放到内存中,获取图片只发生一次 IO 操作。

2. Fault-tolerant. 高可用性是不可避免的话题,haystack 设计时考虑了地域 IDC 容灾和机柜容灾。服务端上传图片时指定冗余策略。

3. Cost-effective. 基于商业共享存储的都比较贵,普通 PC 服务器挂载大硬盘便宜很多,但是故障率也比较高,这一点比较考验 Fault-tolerant 高可用。

4. Simple. 架构简单,部署和运维更方便。最近在研究的 vitess 架构和部署非常复杂,这也是他流行不起来的一个原因。

基于这个思想,haystack 设计者绕过了 POSIX 文件系统这块,把 haystack 变成了一个 KV FS,即 NOFS。每个图片对应一个 FID,不再单独存放文件系统中,而是同一个物理卷 Volume 图片全部写入一个文件中,由 Volume Server 内存维护 FID : <Volume Machine, Offset, Size> 映射关系,Volume Server 内存中维护打开的文件句柄,读取图片时只需一次 IO 顺序读操作。

haystack架构图

架构比较简单,分为三部份:Haystack Directory, Haystack Cache, Haystack Store

Directory: 即所谓的 Meta Server

1. 生成 FID,维护 logical volume 与 physical volume 映射关系,解决上传时的负载均衡问题。

2. 新加入的 Store Server 要在这里注册。

3. 维护 logical volume 的 read-only 属性,只读的 logical volume 不再接受 upload 请求。

4. 决定请求走 CDN 还是内部 Haystack Cache Server.

Cache: 所谓的内部 CDN

1. 对图片 FID 采用一致性 hash 算法保存。

2. 只缓存用户请求,而不是来自 CDN 的请求。

3. 只缓存 write-enabled store 图片,由于上传的时间序,相当于只缓存最新生成的图片。比如说用户刚上传的图片,可能就会存到 Cache 中预热。

Store: 最终落地存储服务

1. 图片顺序追加到一个大文件中,内存中维护图片在文件中的 Offset 和 Size 的索引信息。

2. 为了解决重启快速加载问题,索引信息会单独保存到一个 Index File 中。

Store 存储格式

涉及两类文件, Store File 和 Index File。

Store File Layout

Store File 是一个大文件,文件头为 Superblock 保存全局的版本号等信息。每个图片为一个 Needle 结构,顺序追加到文件尾。每个 Needle 保存图片的 Cookie, Key, Flags, Size, Data, CheckSum等信息,由于脸书上传图片一式四份,四个尺寸共用同一个 Key, 那么就由 Alternate Key 做区分。

Index File Layout

当机器重启后,需要利用 Index File 快速重建内存中图片索引信息。如果没有索引文件,那么顺序扫描 Store File 也可以重建,但耗时。 假设 Needle Index 占用24byte,那么128G内存机器可以存储68亿图片的元数据信息。论文中表示,Index File 异步写,重启后可能会有 Ophen Photo 需要从 Store File 中重建。

图片上传,更新与删除

图片时间序特征很明显,所有的上传,更新与删除均为 Append 追加操作。 Web Server 请求 Directory Server, 获取 Volume Id, Key, Alternate Key, Cookie。Web Server 将这些与图片数据上传到指定 Store 机器上,数据的冗余由 Store 同步完成,强一致。

更新操作与上传一致,更新内存索引信息,数据追加到 Store File 即可。删除操作将内存和 Index File 中的 Flags 标记为删除即可。对于大量删除操作,会产生文件空洞,需要根据一定策略回收。

图片读取

在 Url 中可以解出图片的 Volume Id, Key, Alternate Key, Cookie 信息,Web Server 访问 Directory Server 得到该 Volume Id 所在的 Store Server。再由 Store Server 查询内存中索引信息,根据 Flags 标记判断是否已删除。如果未删除,根据 Offset Size 去 Store File 获取详细数据,解出存储的数据和 Cookie,判断与请求的 Cookie 是否一致,不一致则报错。


Weadfs 

Weadfs 是开源版本的GO实现,代码比较简单易懂。仔细阅读源码,可以加深对 haystack 的理解和认识。看知乎上说好多公司在使用,比较稳定。

1. 脸书的 Paper 里还是有好多细节没有披露,比如 Directory Server 的高可用,如果多个那么数据一致性的保证。从源码上看 Weadfs 通过 Raft 来达到多个 Master Server 的高可用。

2. Weedfs 的 Padding 为8,Size使用4字节,那么单 Volume 文件最大32GB.

3. 相比 haystack, 多了很多实用功能:Gzip压缩,索引信息可以存储在 LevelDB 中,多 Master 高可用,filer server 等等。

BeansDB&FastDFS&HDFS

赶集使用 FastDFS 做图片存储,Tracker Server 对应 haystack 的 Directory Server. 但是 FastDFS是使用 POSIX 文件系统的,IO 压力有些大。

BeansDB 是 nice 在使用的存储,Memcache协议,基于 Bitcask 模型,由 R+W>N 来保证一致性。豆瓣一直在用,存储 mp3 文本 图片信息。

这两个开源产品也是针对小文件存储做的优化,有时间还得好好读读源码加深理解。另外一个 HDFS 用来存储大文件,按块打散存储,适合批量作业,吞吐量大,但时延比较高。

结语

本来要写 Redis Proxy Step By Step 系列的,先耽搁一周,下周继续好了。推荐一首李荣浩的歌 《自拍》。

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

推荐阅读更多精彩内容