图片存储的几个关键点:

1. Metadata信息存储。由于图片数量巨大,单机存放不了所有的Metadata信息,假设每个图片文件的Metadata占用100字节,260 billion图片Metadata占用的空间为260G * 100 = 26000GB。

2. 减少图片读取的IO次数。在普通的Linux文件系统中,读取一个文件包括三次磁盘IO:读取目录元数据到内存,把文件的inode节点装载到内存,最后读取实际的文件内容。由于文件数太多,无法将所有目录及文件的inode信息缓存到内存,因此磁盘IO次数很难达到每个图片读取只需要一次磁盘IO的理想状态。

3. 图片缓存。图片写入以后就不再修改,因此,需要对图片进行缓存并且将缓存放到离用户最近的位置,一般会使用CDN技术。

4. 支持在线扩容,随着图片数量的增加,在线扩容的能力是必须的。

5. 图片处理服务。之前遇到过图片处理问题,当用户短时间内大量上传图片的时候,切图的CPU耗用率非常高,如果直接将切图的任务放在前端服务器上来做,势必会造成前端机器load过高;另一种解决方案是单独拿出机器来做切图服务,切完之后再同步到图片存储服务器,再有一种解决方案就是分布式切图,利用mapreduce来做,把切图压力分散到各台机器上,同时各台机器做存储之用。

各个文件系统的特性摘录:

1 mongoDB GridFS

GridFS是为mongoDB中的大文件存储而设计的,它把大文件分割成多个小文件分别存储,通常每个256K,并且可以存储meta信息。即一个文件上传到mongoDB之后,可能被拆成多个文档存在chunks集合,一个metadata文件存在files集合,支持sharding replication。基于gridFS做得一些解决方案:

a. 国人写的一个解决方案:基于MongoDB GridFS的图片存储 http://liut.cc/blog/2010/12/about-imsto_my-first-open-source-project.html

思路:

  • 决不允许重复图片存在

  • 文件只有原始的需要保留,其他各尺寸和效果都可以由原图生成

  • 图片URL总是固定的,不管它出现在哪里

  • 缩略图生成规则也简单的体现在URL里,参考 Abusing Amazon p_w_picpaths

  • 第一次请求,由图片处理程序生成静态文件,以后请求即直接定位到静态文件

用到的组件:

MongoDB (GridFS): 这个不用说了,核心存储,初期环境用到了三台主机组成的 Replica Sets

Nginx: 解析URL并定位到静态文件,如果未生成则转向uWSGI程序去生成图片

Python + pymongo

ImageMagick: 用来生成图片缩略图,有两种调用方式:Api和命令行shell。Demo环境由于内存使用限制,用了shell方式。

uWSGI: 是用纯C写的WSGI服务器,支持多种语言(主要是Python)和Web Server(官方首推Cherokee和Nginx)。有点儿类似PHP-FPM。

b. nginx-gridfs Nginx module for serving files from MongoDB’s GridFS(nginx + gridfs 实现图片的分布式存储(一) 安装

这是gridfs的nginx module. 可以通过nginx直接访问读取mongo gridfs中的文件.

和nginx对应的mogilefs module类似.

优点: 由于直接通过nginx,速度是最快的.
缺点: 只能通过file_path来查找,目前不支持_id来查找.因此必须在file_path上建立索引.

方案:

1. squid/varnish+script-backend
在nginx前端加上一个squid或者varnish作为反向加速. 如果没有则通过 PHP脚本来获取.
应用场景: 特别适合读取频繁的文件,比如用户的头像,热门图片,缩略图等. 不适合大文件.
缺点: 文件的过期必须正确设置. 此外配置好varnish或者squid

2. 基于proxy_store或fastcgi-cache, try_files
这种方案的应用场景同1, 但都是使用nginx的相应模块即可实现.
通过对fastcgi/proxy进行cache或store,就可以实现文件按需存储.
当使用proxy_store时,当后端文件变动时,需要purge这些文件.实现起来不难.

MogileFS

MogileFS is our open source distributed filesystem. Its properties and features include:

  • Application level – no special kernel modules required.

  • No single point of failure – all three components of a MogileFS setup (storage nodes, trackers, and the tracker’s database(s)) can be run on multiple machines, so there’s no single point of failure. (you can run trackers on the same machines as storage nodes, too, so you don’t need 4 machines…) A minimum of 2 machines is recommended.

  • Automatic file replication – files, based on their “class”, are automatically replicated between enough different storage nodes as to satisfy the minimum replica count as requested by their class. For instance, for a photo hosting site you can make original JPEGs have a minimum replica count of 3, but thumbnails and scaled versions only have a replica count of 1 or 2. If you lose the only copy of a thumbnail, the application can just rebuild it. In this way, MogileFS (without RAID) can save money on disks that would otherwise be storing multiple copies of data unnecessarily.

  • “Better than RAID” – in a non-SAN RAID setup, the disks are redundant, but the host isn’t. If you lose the entire machine, the files are inaccessible. MogileFS replicates the files between devices which are on different hosts, so files are always available.

  • Flat Namespace – Files are identified by named keys in a flat, global namespace. You can create as many namespaces as you’d like, so multiple applications with potentially conflicting keys can run on the same MogileFS installation.

  • Shared-Nothing – MogileFS doesn’t depend on a pricey SAN with shared disks. Every machine maintains its own local disks.

  • No RAID required – Local disks on MogileFS storage nodes can be in a RAID, or not. It’s cheaper not to, as RAID doesn’t buy you any safety that MogileFS doesn’t already provide.

  • Local filesystem agnostic – Local disks on MogileFS storage nodes can be formatted with your filesystem of choice (ext3, XFS, etc..). MogileFS does its own internal directory hashing so it doesn’t hit filesystem limits such as “max files per directory” or “max directories per directory”. Use what you’re comfortable with.

MogileFS is not:

  • POSIX Compliant – you don’t run regular Unix applications or databases against MogileFS. It’s meant for archiving write-once files and doing only sequential reads. (though you can modify a file by way of overwriting it with a new version) Notes:** Yes, this means your application has to specifically use a MogileFS client library to store and retrieve files. The steps in general are 1) talk to a tracker about what you want to put or get, 2) read/write to one of the places it told you you could (it’ll pick storage node(s) for you as part of its load balancing), using HTTP GET/PUT** We’ve prototyped a FUSE binding, so you could use MogileFS without application support, but it’s not production-ready.

  • Completely portable … yet – we have some Linux-isms in our code, at least in the HTTP transport code. Our plan is to scrap that and make it portable, though.

MongoDB (GridFS): 这个不用说了,核心存储,初期环境用到了三台主机组成的 Replica Sets
Nginx: 解析URL并定位到静态文件,如果未生成则转向uWSGI程序去生成图片
Python + pymongo
ImageMagick: 用来生成图片缩略图,有两种调用方式:Api和命令行shell。Demo环境由于内存使用限制,用了shell方式。
uWSGI: 是用纯C写的WSGI服务器,支持多种语言(主要是Python)和Web Server(官方首推Cherokee和Nginx)。有点儿类似PHP-FPM。

3 FaceBook Haystack

http://www.facebook.com/note.php?note_id=76191543919

Haystack提出了一种通用的基于HTTP的对象存储,它含有指针,映射到存储对象。在Haystack中以指针储存照片,把数以十万计的图像聚集到一个Haystack存储文件,从而消除了元数据负荷。这就使得元数据的开销非常小,并且使我们能够在存储文件和内存索引中存储每个指针的位置。这就使得能用少量的I/O操作来完成图像数据的检索,可以消除一切不必要的元数据开销。

HayStack的主要目标:http://www.chinadaily.com.cn/micro-reading/tech/2011-05-16/content_2617837.html

1. High throughput and low latency(高吞吐量、低延时):简化元数据结构与存储模式,直接存储文件在物理卷上的位置,减小lookup时间。

2. Fault-tolerant(容错性):在不同的机器上维护多个副本

3. Cost-effective(高效):提高存储空间利用率、提高请求处理效率。

4. Simple(简单):易于实现和维护,部署周期短。

Haystack Directory的主要功能如下:

1, 提供逻辑卷轴到物理卷轴的映射,为写请求分配图片id;

2, 提供负载均衡,为写操作选择逻辑卷轴,读操作选择物理卷轴;

3, 屏蔽CDN服务,可以选择某些图片请求直接走HayStack Cache;

4, 标记某些逻辑卷轴为read-only;

4 淘宝TFS

TFS(Taobao FileSystem)是一个高可扩展、高可用、高性能、面向互联网服务的分布式文件系统,主要针对海量的非结构化数据,它构筑在普通的Linux机器集群上,可为外部提供高可靠和高并发的存储访问。TFS为淘宝提供海量小文件存储,通常文件大小不超过1M,满足了淘宝对小文件存储的需求,被广泛地应用在淘宝各项应用中。它采用了HA架构和平滑扩容,保证了整个文件系统的可用性和扩展性。同时扁平化的数据组织结构,可将文件名映射到文件的物理地址,简化了文件的访问流程,一定程度上为TFS提供了良好的读写性能。http://code.taobao.org/trac/tfs/wiki/intro