我目前正在为基于Web的应用程序设计架构,该架构还应提供某种图像存储。用户可以将照片上传为服务的关键功能之一。同时查看这些图像将是主要用途之一(通过网络)。
但是,我不确定如何在我的应用程序中实现这样的可伸缩图像存储组件。我已经考虑过不同的解决方案,但由于缺少经验,我期待听到您的建议。除了图像之外,还必须保存元数据。 以下是我最初的想法:
使用像HDFS这样的(分布式)文件系统,并将专用的Web服务器准备为“文件系统客户端”,以便保存上传的图像和服务请求。图像元数据保存在附加数据库中,包括每个图像的文件路径信息。
在HDFS之上使用像HBase这样的面向BigTable的系统,并将图像和元数据保存在一起。同样,Web服务器桥接图像上传和请求。
使用像CouchDB这样的完全无模式数据库来存储图像和元数据。此外,使用基于HTTP的RESTful API将数据库本身用于上载和发送。 (附加问题:CouchDB确实通过Base64保存blob。但它能否以image / jpeg等形式返回数据)?
答案 0 :(得分:42)
我们一直在使用CouchDB,将图像保存为“附件”。但是一年后,数十个GB CouchDB数据库文件变得令人头疼。例如,如果您使用非常大的文档大小,CouchDB复制仍会出现问题。
所以我们只是重写了我们的软件,使用CouchDB获取图像信息,使用Amazon S3实现图像存储。该代码位于http://github.com/hudora/huImages
您可能希望为您的项目在现场设置与Amazon S3兼容的存储服务。这使您保持灵活性,并且不需要外部服务就可以保留亚马逊选项。 Walruss似乎成为最受欢迎且可扩展的S3克隆。
我还恳请您通过他们出色的开源MogileFS和Perlbal产品来研究Livejournal的设计。 This combination可能是最着名的图像投放设置。
flickr Architecture也可以成为一种灵感,虽然它们不像Livejournal那样向公众提供开源软件。
答案 1 :(得分:14)
“其他问题:CouchDB确实通过Base64保存blob。”
CouchDB 不将blob保存为Base64,它们存储为直接二进制文件。在使用?attachments=true
检索JSON文档时,我们会将磁盘上的二进制文件转换为Base64,以便将其安全地添加到JSON,但这只是一个表示级别的事情。
CouchDB为附件提供与其存储的内容类型,实际上通常可以直接向浏览器提供HTML,CSS和GIF / PNG / JPEG附件。
附件可以流式传输,在CouchDB 1.1中,甚至支持Range标头(用于媒体流和/或恢复中断的下载)。
答案 2 :(得分:8)
使用Seaweed-FS(以前称为Weed-FS),这是Facebook干草堆纸的实现。
Seaweed-FS非常灵活,简化了基础知识。它的创建是为了存储数十亿张图像并快速为它们服务。
答案 3 :(得分:3)
您是否考虑过亚马逊网络服务? S3是基于Web的文件存储,SimpleDB是key->属性存储。两者都具有高性能和高度可扩展性。它比维护自己的服务器和设置更昂贵(假设你要自己做,而不是雇用人员),但你可以更快地启动和运行。
编辑:我接受了这一点 - 从长远来看,它的价格较高,但是对于低销量而言,它会超过购买硬件的初始成本。
S3:http://aws.amazon.com/s3/(你可以在这里存储你的图像文件,并且为了提高性能可能在你的服务器上有一个图像缓存,或者可能没有)
SimpleDB:http://aws.amazon.com/simpledb/(元数据可以在此处:图像ID映射到您要存储的任何数据)
编辑2:我甚至不知道这一点,但有一个名为Amazon CloudFront的新网络服务(http://aws.amazon.com/cloudfront/)。它用于快速Web内容交付,并且与S3完美集成。有点像Akamai的图像。您可以使用此代替图像缓存。
答案 4 :(得分:3)
也许看一下Facebook hayStack的描述
Needle in a haystack: efficient storage of billions of photos
答案 5 :(得分:3)
我们使用MogileFS。我们是小规模用户,小于8TB,文件大约有5000万。几年前我们从存储在Amazon S3中切换到更好地控制文件名和性能。
这不是最漂亮的软件,但它经过了“现场测试”,基本上所有用户都以同样的方式使用它。
答案 6 :(得分:2)
作为Cloudant的一部分,我不想推销产品....但BigCouch在我的科学应用程序堆栈中解决了这个问题(物理 - 与Cloudant无关,当然与利润无关!)。它将CocuhDB设计的简单性与单服务器CouchDB中缺少的自动分片和可扩展性结合在一起。我一般用它来存储较小数量的大文件(多GB)和大量小文件(100MB或更少)。我使用的是S3,但实际上,获取成本开始累计重复访问的小文件。
答案 7 :(得分:1)
好的,如果所有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下从磁盘提供它们。
答案 8 :(得分:1)
我一直在试验我的Python视图服务器中CouchDB视图服务器可用的一些_update功能。
我做的一件非常酷的事情是图片上传的更新功能,这样我就可以使用PIL创建缩略图和其他相关图像,并在将它们推送到CouchDB时将它们附加到文档中。
如果您需要图像处理并希望减少需要跟上的代码和基础架构数量,这可能很有用。
答案 9 :(得分:1)
我在cassandra上写过图像存储。我们有很多写入和随机读取读/写是低。对于高读/写比率,我建议你使用mongodb(GridFs)。
答案 10 :(得分:-1)
以下是使用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);
...
与存储单张图像相同。