スケーラブルな画像ストレージ
質問
現在、Webベースのアプリケーション用のアーキテクチャを設計しています。これは、ある種の画像ストレージも提供する必要があります。ユーザーは、サービスの重要な機能の1つとして写真をアップロードできます。また、これらの画像を表示することは、主要な使用法の1つです(Web経由)。
ただし、アプリケーションでこのようなスケーラブルな画像ストレージコンポーネントをどのように実現するかはわかりません。私はすでにさまざまな解決策について考えましたが、経験が欠けているため、あなたの提案を聞くことを楽しみにしています。画像とは別に、メタデータもゼロでなければなりません。これが私の最初の考えです:
アップロードされた画像とサービスリクエストを保存するために、HDFSなどの(分散)ファイルシステムを使用して、専用のWebサーバーを「ファイルシステムクライアント」として準備します。画像メタデータは、各画像のFilePath情報を含む追加のデータベースに保存されます。
HDFSの上にHBaseなどのビッグテーブル指向のシステムを使用し、画像とメタデータを一緒に保存します。繰り返しますが、WebServers Bridge Imageのアップロードとリクエスト。
画像とメタデータの両方を保存するには、CouchDBのような完全にSchemalessデータベースを使用してください。さらに、HTTPベースのRESTFUL APIを使用して、データベース自体をアップロードして削除するために使用します。 (追加の質問:couchdbはbase64を介してブロブを保存します。ただし、画像/jpegなどの形式でデータを返すことはできますか?)?
解決
そのためにCouchDBを使用して、画像を「添付ファイル」として保存しています。しかし、1年後、複数のGB CouchDBデータベースファイルが頭痛であることが判明しました。たとえば、CouchDBレプリケーションには、非常に大きなドキュメントサイズで使用している場合、まだ問題があります。
そのため、ソフトウェアを書き換えて、画像情報にCouchDBを使用し、実際の画像ストレージにはAmazon S3を使用します。コードはで利用できます http://github.com/hudora/huimages
プロジェクトのために、Amazon S3互換ストレージサービスをオンサイトでセットアップすることをお勧めします。これにより、柔軟性が維持され、今のところ外部サービスを必要とせずにAmazonオプションを残します。 ウォルス 最も人気があり、スケーラブルなS3クローンになっているようです。
また、優れたオープンソースでLiveJournalのデザインを調べることをお勧めします mogilefs と Perlbal 提供。 この組み合わせ おそらく、セットアップを提供する最も有名な画像です。
また Flickrアーキテクチャ LiveJournalのように、オープンソースソフトウェアを一般に提供していませんが、インスピレーションになる可能性があります。
他のヒント
「追加の質問:CouchDBはBase64を介してブロブを保存します。」
couchdbはそうします いいえ blobsをbase64として保存すると、ストレートバイナリとして保存されます。 JSONドキュメントを取得するとき ?attachments=true
JSONに安全に追加するために、オンディスクバイナリをBase64に変換しますが、それは単なるプレゼンテーションレベルのことです。
見る スタンドアロンの添付ファイル.
CouchDBは、添付ファイルを添付して添付しています。実際には、サーバーHTML、CSS、GIF/PNG/JPEGアタッチメントに直接ブラウザに直接添付される可能性があります。
添付ファイルをストリーミングし、CouchDB 1.1では、レンジヘッダーをサポートします(メディアストリーミングおよび/または中断されたダウンロードの再開用)。
使用する 海藻-fs (以前はWeed-FSと呼ばれていました)、FacebookのHaystack Paperの実装。
Seaweed-FSは非常に柔軟であり、基本に分類されています。数十億の画像を保存し、それらを速く提供するために作成されました。
Amazon Webサービスを検討しましたか? S3はWebベースのファイルストレージであり、SimpleDBはキー - >属性ストアです。どちらもパフォーマンスがあり、非常にスケーラブルです。独自のサーバーやセットアップを維持するよりも高価です(自分でやろうとしていると仮定して、人を雇うことはないと仮定します)が、より迅速に稼働します。
編集:私はそれを取り戻します - 長期的には大量に高価ですが、低ボリュームではハードウェアの購入の初期コストに勝ちます。
S3: http://aws.amazon.com/s3/ (ここに画像ファイルを保存できます。パフォーマンスのために、サーバーに画像キャッシュがあるか、そうでない場合があります)
SimpleDB: http://aws.amazon.com/simpledb/ (メタデータはここに行くことができます:保存するデータへの画像IDマッピング)
編集2:私はこれについても知りませんでしたが、Amazon CloudFrontという新しいWebサービスがあります(http://aws.amazon.com/cloudfront/)。これは、高速のWebコンテンツ配信用であり、S3とうまく統合されています。あなたの画像のためのアカマイのようなものです。画像キャッシュの代わりにこれを使用できます。
Mogilefsを使用します。私たちは、8TB未満と約5,000万のファイルを持つ小規模ユーザーです。数年前にAmazon S3に保管することから、ファイル名とパフォーマンスをよりよく制御できるようになりました。
それは最もきれいなソフトウェアではありませんが、それは非常に「フィールドテスト」されており、基本的にすべてのユーザーがあなたと同じようにそれを使用しています。
Facebook Haystackの説明を見てください
Cloudantの一部として、私は製品をプッシュしたくありません....しかし、BigCouchは私の科学アプリケーションスタックでこの問題を解決します(物理学 - Cloudantとは何の関係も、利益とは何の関係もありません!)。シングルサーバーCouchDBで欠落している自動型およびスケーラビリティとCocuHDB設計のシンプルさを結婚させます。通常、私はそれを使用して、少数の大きなファイル(マルチGB)と多数の小さなファイル(100MB以下)を保存します。私はS3を使用していましたが、GETコストは実際に繰り返しアクセスされる小さなファイルのために追加され始めます。
OK、AWSのすべてがうまくいかない場合、ここにいくつかの考えがあります。
(3)に関しては、バイナリデータをデータベースに入力すると、同じデータが発表されます。 JPEGになるのは、データベースが考えているものではなく、データの形式です。クライアント(Webブラウザー)にJPEGが設定されたときだと思う理由 Content-type
ヘッダーに image/jpeg
. 。また、テキストのような他の(推奨されない)に設定することもできます。これがブラウザがそれを解釈しようとする方法です。
ディスク上のストレージの場合、私はそのシンプルさのためにCouchDBが好きですが、HDFSは確かに機能します。 CouchDBからの画像コンテンツの提供に関する投稿へのリンクは次のとおりです。 http://japhr.blogspot.com/2009/04/render-couchdb-images-via-sinatra.html
編集:Linux/Apacheの下でディスクからそれらを提供するMemcached vsのキャッシュ画像に関する有用な議論へのリンクを次に示します。
Python View ServerのCouchDBビューサーバーが利用できる_Update機能のいくつかを実験しています。
私が本当にクールなことをしたことの1つは、画像アップロードの更新機能でした。これにより、PILを使用してサムネイルやその他の関連画像を作成し、CouchDBに押し込まれたときにドキュメントに添付できます。
これは、画像操作が必要であり、追いつくために必要なコードとインフラストラクチャの量を削減したい場合に役立つ場合があります。
Cassandraの上に画像ストアを書きました。私たちはたくさんの書き込みとランダムな読み取りを読み取り/書き込みが低いです。高い読み取り/書き込み比については、mongodb(gridfs)をお勧めします。
PHP Laravelを使用してCouchDBにBlob画像を保存する例を以下に示します。この例では、ユーザーの要件に基づいて3つの画像を保存しています。
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);
...
単一の画像を保存できるのと同じです。