可扩展的图像存储

Posted

技术标签:

【中文标题】可扩展的图像存储【英文标题】:Scalable Image Storage 【发布时间】:2010-12-29 23:48:02 【问题描述】:

我目前正在为基于 Web 的应用程序设计一个架构,该应用程序还应该提供某种图像存储。用户将能够上传照片作为该服务的主要功能之一。查看这些图像也是主要用途之一(通过网络)。

但是,我不确定如何在我的应用程序中实现这种组件。我已经考虑过不同的解决方案,但由于缺少经验,我期待听到您的建议。除了图像,还必须保存元数据。 以下是我最初的想法:

    使用像 HDFS 这样的(分布式)文件系统,并准备专用的网络服务器作为“文件系统客户端”,以保存上传的图像和服务请求。图像元数据保存在一个附加数据库中,包括每个图像的文件路径信息。

    在 HDFS 之上使用 HBase 等面向 BigTable 的系统,并将图像和元数据一起保存。同样,网络服务器桥接图像上传和请求。

    使用像 CouchDB 这样完全无模式的数据库来存储图像和元数据。此外,使用基于 HTTP 的 RESTful API 使用数据库本身进行上传和交付。 (附加问题:CouchDB 确实通过 Base64 保存 blob。但是它能否以图像/jpeg 等形式返回数据)?

【问题讨论】:

【参考方案1】:

为此,我们一直在使用 CouchDB,将图像保存为“附件”。但一年后,数十个 GB CouchDB 数据库文件变得令人头疼。例如,如果您将 CouchDB 复制用于非常大的文档大小,它仍然会出现问题。

所以我们只是重写了我们的软件,使用 CouchDB 存储图像信息,使用 Amazon S3 存储实际图像。代码可在http://github.com/hudora/huImages获得

您可能希望为您的项目现场设置与 Amazon S3 兼容的存储服务。这使您保持灵活性,并且暂时无需外部服务即可离开亚马逊选项。 Walruss 似乎成为最流行和可扩展的 S3 克隆。

我还敦促您研究 Livejournal 的设计及其出色的开源 MogileFS 和 Perlbal 产品。 This combination 可能是最著名的图像服务设置。

flickr Architecture 也可以成为一种灵感,尽管他们不像 Livejournal 那样向公众提供开源软件。

【讨论】:

您能否详细说明一下您是如何实现图像存储的。特别有意思的是你是怎么做授权的。 授权只能通过不可猜测的 URL。 我的意思是从一方面你必须在图像存储中添加图像,并且这个功能应该对需要验证的特定用户可用。另一方面,每个人都应该可以读取,以便图像可以实际显示给用户。 啊,我明白了。 CouchDB 只能由我们的内部服务器访问。他们都有完整的 r/w/ 许可。能够上传的其他权限由网络应用程序处理。 bitbucket.org/petrilli/django-storages/src/5cac7fceb0f8/… 是我们一直在使用的齿轮之一。 对于那些正在寻找解决这个问题的替代方案的人,RiakCS 现在可以开源并提供与 S3 兼容的 API:basho.com/riak-cloud-storage【参考方案2】:

“附加问题:CouchDB 确实通过 Base64 保存 blob。”

CouchDB 将 blob 保存为 Base64,它们存储为直接二进制文件。当使用?attachments=true 检索 JSON 文档时,我们会将磁盘上的二进制文件转换为 Base64,以便将其安全地添加到 JSON 中,但这只是表示级别的事情。

见Standalone Attachments。

CouchDB 使用它们存储的内容类型来提供附件,实际上很常见的是,将 html、CSS 和 GIF/PNG/JPEG 附件直接提供给浏览器。

附件可以流式传输,在 CouchDB 1.1 中,甚至支持 Range 标头(用于媒体流式传输和/或恢复中断的下载)。

【讨论】:

在写这个问题的时候,它们确实被存储为 Base64。 CouchDB 从未将附件存储为 Base64。可能误导您的是要求 CouchDB 返回带有您文档 JSON 的附件的能力。为此,有必要将它们包装在 Base64 中。在磁盘上,它始终是真正的字节。 是的,我的评论具有误导性。我指的不是底层存储机制,而是通过 API 访问附件的方式。【参考方案3】:

使用Seaweed-FS(以前称为 Weed-FS),这是 Facebook 干草堆论文的一种实现。

Seaweed-FS 非常灵活并且精简到了基础。它的创建是为了存储数十亿张图像并快速提供服务。

【讨论】:

你好。我们有 1 台服务器,其中包含 ~3m 的缩略图。在高峰时间,它每秒处理12k 个请求。一切都很好,所以尝试一下 weed-fs 是个好主意【参考方案4】:

您是否考虑过亚马逊网络服务? S3是基于web的文件存储,SimpleDB是key->attribute store。两者都是高性能和高度可扩展的。它比维护自己的服务器和设置要贵(假设您要自己做而不是雇用人员),但是您可以更快地启动和运行。

编辑:我收回这一点 - 从长远来看,大批量生产成本更高,但对于小批量生产,它超过了购买硬件的初始成本。

S3:http://aws.amazon.com/s3/(您可以将图像文件存储在这里,为了提高性能,您的服务器上可能有图像缓存,也可能没有)

SimpleDB:http://aws.amazon.com/simpledb/(元数据可以放在这里:图像 id 映射到您想要存储的任何数据)

编辑 2:我什至不知道这一点,但有一个名为 Amazon CloudFront (http://aws.amazon.com/cloudfront/) 的新 Web 服务。它用于快速 Web 内容交付,并且与 S3 很好地集成。有点像 Akamai 的图像。您可以使用它来代替图像缓存。

【讨论】:

谢谢你的想法,我已经考虑过了。但是,这是一个教育项目,我们不能使用外部服务,尤其是我们不能花钱购买它们。不幸的是,S3 和 SimpleDB 都不是我们的选择。 哦。那么,也许把它放在问题中。 既然不能花钱,那你的硬件限制是什么? 我们可以获得作为内部虚拟化服务器的必要数量的硬件。它也是一个概念验证项目,至少在开始时没有从外部使用任何应用程序。然而,可扩展性问题是主要的项目影响之一,因此应该考虑到远见。【参考方案5】:

我们使用 MogileFS。我们是少于 8TB 和大约 5000 万个文件的小规模用户。几年前,我们从存储在 Amazon S3 中转变为更好地控制文件名和性能。

它不是最漂亮的软件,但它经过了“现场测试”,基本上所有用户都在使用它。

【讨论】:

据我了解,MogileFS 比分布式数据库更适合此任务(在其中存储文件不是一件很自然的事情),并且更适合于例如HDFS(适用于大文件,切片可以存储在不同的节点上,有利于 MapReduce 数据本地化)。图像是不需要切片的小文件,MogileFS 看起来可以有效地处理这个问题,因为它是为满足这个目的而编写的(用于 LiveJournal.com)。【参考方案6】:

作为 Cloudant 的一部分,我不想推产品....但是 BigCouch 在我的科学应用程序堆栈中解决了这个问题(物理学——与 Cloudant 无关,当然也与利润无关!)。它将 CocuhDB 设计的简单性与单服务器 CouchDB 中缺少的自动分片和可伸缩性结合在一起。我一般用它来存储少量的大文件(多 GB)和大量的小文件(100MB 或更少)。我使用的是 S3,但对于重复访问的小文件,获取成本实际上开始增加。

【讨论】:

您是否考虑过在 couchdb 之上使用 http 缓存来缓存图像,例如 Akamai 或 Varnish? I was using S3 but the get costs actually start to add up for small files that are repeatedly accessed. 默认情况下,Amazon S3 不会为图像设置缓存过期标头,这本身可能会在一定程度上计入账单。您应该考虑自己设置。【参考方案7】:

也许看看 Facebook hayStack 的描述

Needle in a haystack: efficient storage of billions of photos

【讨论】:

如果您的答案包含您链接到的一些信息,那将会很有用。特别是因为您已链接到需要 Facebook 登录的文档,这似乎对我来说等同于无法访问。【参考方案8】:

好的,如果 AWS 的所有东西都不起作用,这里有几个想法。

就(3)而言,如果将二进制数据放入数据库中,则会输出相同的数据。使它成为 jpeg 的是数据的格式,而不是数据库认为的格式。当您将Content-type 标头设置为image/jpeg 时,让客户端(Web 浏览器)认为它是 jpeg 的原因。您也可以将其设置为其他内容(不推荐),例如文本,这就是浏览器尝试解释它的方式。

对于磁盘存储,我喜欢 CouchDB 的简单性,但 HDFS 肯定可以。这是一篇关于从 CouchDB 提供图像内容的帖子的链接:http://japhr.blogspot.com/2009/04/render-couchdb-images-via-sinatra.html

编辑:这里有一个有用的讨论链接,讨论在 memcached 中缓存图像与在 linux/apache 下从磁盘提供图像。

【讨论】:

你说here's a link to a useful discussion...链接丢失了吗?【参考方案9】:

我一直在我的 Python 视图服务器中试验 CouchDB 视图服务器可用的一些 _update 功能。

我做的一件很酷的事情是图片上传的更新功能,这样我就可以使用 PIL 创建缩略图和其他相关图片,并在它们被推送到 CouchDB 时将它们附加到文档中。

如果您需要图像处理并希望减少需要跟上的代码量和基础架构,这可能会很有用。

【讨论】:

【参考方案10】:

我已经在 cassandra 之上编写了图像存储。我们有很多,写入和随机读取读/写很低。对于高读/写比率,我建议您使用 mongodb (GridFs)。

【讨论】:

这很有趣!我现在写同样的东西。但我无法想象这种存储方法的好坏。你还在用这个方法吗?您存储了多少内容? 现在 4 PB,我现在转移到 hadoop。 每个节点存储多少数据?您是否有压缩问题(您说您的案例是重写)。维修效率如何? @odiszapc 我不再使用 cassandra。我每个节点有 500G 到 2T。 Cassandra 满足可用性和“自动”扩展。一致性和容量规划存在很多问题。我对压缩没有问题,只写,任何更新都非常罕见。 你说你也搬了Hadoop。 Hadoop 是 MapR 框架。您是否谈到迁移到 HDFS?【参考方案11】:

这是一个使用 php Laravel 在 CouchDB 中存储 blob 图像的示例。 在此示例中,我根据用户要求存储了三张图像。

在 CouchDB 中建立连接。

$connection = DB::connection('your database name');

/*region Fetching the Uers Uploaded Images*/

$FirstImage = base64_encode(file_get_contents(Input::file('FirstImageInput')));
$SecondImage =base64_encode(file_get_contents(Input::file('SecondImageInput')));
$ThirdImage = base64_encode(file_get_contents(Input::file('ThirdImageInput')));

list($id, $rev) = $connection->putDocument(array(
    'name' => $name,
    'location' => $location,
    'phone' => $phone,
    'website' => $website,
    "_attachments" =>[
        'FirstImage.png' => [
            'content_type' => "image/png",
            'data' => $FirstImage
        ],
        'SecondImage.png' => [
            'content_type' => "image/png",
            'data' => $SecondImage
        ],
        'ThirdImage.png' => [
            'content_type' => "image/png",
            'data' => $ThirdImage
        ]
    ],
), $id, $rev);

...

与存储单个图像相同。

【讨论】:

以上是关于可扩展的图像存储的主要内容,如果未能解决你的问题,请参考以下文章

动态水平可扩展键值存储

为啥 AssocQueryString 找不到与图像扩展关联的可执行文件?

带有图像的可扩展字符串不适用于推送通知

可扩展数据库模式 - 如何存储可扩展属性值

可扩展拉伸图像按钮

Gitlab 中存储库的可扩展存储