概览
Haystack 的基本思想就是将索引信息放在内存中,避免额外的IO。为了做到这一点,主要进行了两方面的设计:
- 将小文件集合成大文件,减少文件数,从而减少了元信息的数目。
- 精简文件元信息,去掉一切在 Facebook 场景中不需要的 POSIX 语义中元信息。
这样就可以将数据元信息减小到一个内存可以放的下的量级,基本上每次每次数据访问同一个一次 IO 就可以完成,而非以前的好几次。
Facebook业务量级
2600w, 20P
峰值每秒钟100w图片。
key observation
传统文件系统设计导致了过多的元信息查找,我们进行的减少了每个图片的元信息使得Haystack 能够在内存中进行所有的元信息查找操作。
定位
是一个对象存储,用来存分享的图片,针对的是一次写,经常读,从来不改,很少删的数据集。不得不造轮子,因为传统的分拣系统在如此高并发下,表现太差。
缘起
POSIX:目录组织,并且每个文件存了过多的我们用不到的元信息,如用户许可权。而在读文件的时候,元信息必须预先读入内存,在有数十亿量级的文件时,这几乎是不可忍受的。尤其对于NAS(network attached storage)
一个图片读写需要三次访问磁碟:
- 将文件名翻译为inode
- 从磁碟读入inode
- 根据inode信息读文件本身
特点
高并发低延迟: CDN太贵,只能减少单个文件的metadata,然后将所有metadata保存在内存中,尽量做到一次访盘。
容错:异地备份
花销: 比 CND 便宜。
简单: 没有那么长时间的完善和测试,为了可用,只能做到尽量简单。
旧流程
首先访问 webserver,获取图片的的全局URL,里面包含图片的位置信息。然后用CDN做缓存,命中返回,否则去 photo storage载入到CDN再访问。
一个文件夹存数千张图片的时候,目录到block映射增大,一次不能载入内存,更加重了访问次数。
总之,我们明白了无论是内部缓存还是外部缓存(memcached),都无助于长尾形式的访问流量。
RAM-to-disk 比率,提高这个比率,但是一个图片最少占一个inode,从而带来至少数百比特的额外元信息占用。
新设计
传统来说,如果网页静态内容服务如果出现瓶颈,就用CDN来解决。但是长尾文件的访问还需灵眸他路,当然我们承认非热门图片的请求是可以访盘的,但是我们可以减少这个次数。
一个图片存一个文件元信息太多,那么直观的想法就是一堆图片存成一个文件。
接下来我们区分两种元信息:
- 应用元信息,用来构建浏览器可以用来检索图片的URL。
- 文件系统元信息,用以让某个主机在其磁碟上定位该图片。
概览
三个主要组件:Haystack Store, Haystack Directory, Haystack Cache,简略起见,我们将 Haystack 省略代称为存储,目录和缓存。
- Store 对图片的持久化层做了封装,是唯一管理图片文件元信息的组件。实现上来说,我们将主机的存储进行划分,称为一个个物理上的 Volume。然后不同主机上的某几个物理 volume 作为一组称为一个逻辑上的 volume。那么这几个物理上的volume就是该逻辑 volume 的 replica,以进行备份,容错和分流。
- Directory 维护了逻辑到物理的映射,以及另外一些应用信息,包括图片到逻辑volume的映射,有空闲空间的逻辑volume
- Cache 起内部CDN的作用。当对热门图片的请求过来时,上层CDN不可用或者没命中时,屏蔽了直接对store的访问。
一个典型的要访问CDN的图片请求URL长这样:http://?CDN?/?Cache?/?Machine id?/?Logical volume, Photo?
在CDN,Cache,Machine,层如果命中就返回,否则剥离该层次地址,然后将请求转发到下一层。