MongoDB GridFSについて

今回はMongoDBのGridFSを少しだけ触ってみました。

This allows us to efficiently store large objects, and in the case of especially large files, such as videos, permits range operations (e.g., fetching only the first N bytes of a file).

MongoDBはデータをBSONと呼ばれる形式で扱っていますが、一つのBSONオブジェクトに対して16MBの制限(v1.7未満のバージョンだと4MB)があるようです。GridFSはMongoDBに巨大なファイルを格納するための仕様で、公式でも上記引用の通り動画像ファイルなどを扱うことを想定しているので、ここでは動画配信サービスのバックエンドの一部に使えるかどうか考えてみたいと思います。

* DRMパッケージやエンコード済み動画像ファイルのみを管理したい (元素材は管理しない)
* タイトルや著作権情報、エンコードプロファイル等のメタデータも併せて管理したい
* プログラムから動画像ファイルのデータを一部だけ取得したい
* 過去に保存したファイルも取得したい (エンコードプロファイル変更前後の比較検証のため)

CPとの契約上、元素材の管理は厳しいはずなので、GridFSでは元素材は保存せずにあくまでテンポラリーストレージとして利用することを想定します。つまり信頼性はあまり気にしないということです(もしファイル破損して修復も難しそうだったら、元素材が保存されているストレージから再度取得すればいい)。

テスト環境は”さくらのVPS 512MB”です。GridFSの検証をするにはディスク容量が少なすぎるのでとりあえずは機能の確認だけします。本当は4GB超のファイルを使って検証すべきなんでしょうが容量的に難しいので。。

mongofiles

GridFSを操作するために mongofiles というコマンドラインツールが付属しています。16MB超の動画像ファイルを準備してテストしてみます(動画像ファイルはffmpegで用意すると楽です)。

MongoDBのログには以下のように出力されていました。ディスクスペースがプリアロケーション済みの場合、600MB程度のファイルだと20秒ほど時間がかかっています。

コレクションの中身は以下のようになっています。

自動的に “filename” フィールドにもインデックスを貼ってくれるようです。親切ですね。

プログラムから操作

いろいろな言語のドライバを使ってみましたが、C++ドライバ(doxygen documentation)とPythonドライバ(PyMongo)はGridFS対応も丁寧だったので今回はこれを利用します。

* C++ドライバ

* 出力例

見てわかるようにかなり高級なインタフェースで操作できます。また、mongo::GridFS クラスのメソッドは mongo::DBClientConnection クラスのメソッドのラッパーになっているものが多いので、mongo::BSONObjmongo::BSONElement クラスの仕様と併せて理解しておくと良いかと思います。あと、戻り値として std::auto_ptr<mongo::DBClientCursor> を返してくるメソッドもあるので注意が必要です。C++ドライバについては以前にも紹介しているのでもし興味があれば参照ください。業務ではこのC++ドライバを使って共有ライブラリ(.so)を作ることが多いです。
* MongoDB C++クライアント

次はPythonから操作してみます。
* Pythonドライバ

* 出力例

使い捨てのバッチなどはPythonドライバを使ってさっと書いてしまうと良いかと思います。

GridFSではファイルをバージョニングしているので、過去に保存したファイルも取得することができます。また上記のPythonの例では、任意のメタデータ(copyright)をアドホックに追加していますが、ここはMongoDBの特性がよく表れているところですね。動画配信サービスでは著作権情報や配信期間などメタデータの管理が大変で、特にエンコードプロファイルは変更/追加頻度が高いのでMySQLなどのRDBMSだと素早い対応が難しいです。MongoDBを使えば手間が少し省けるかもしれません。

ファイルの中身を読む

動画像ファイル自体のメタデータを取得するために構造解析を行うことはよくあります。ここではGridFSに保存されたmp4ファイル(AVC/H.264 + AAC)がちゃんと読めるか確認しておきます。ここではMP4のMovie Header(mvhd)から timescale と duration の値を取得して動画の尺を求めます。

動画像ファイル全体を丁寧に解析したい場合はMP4Boxなどの外部プログラムを使った方が楽なんですが、データの一部だけ解析したい場合はプログラムを書いた方が早いのでその辺りは状況に応じて。

今回はMongoDB GridFSの機能をひととおり触ってみました。実際に動画像ファイルのストレージとして運用する場合は容量も必要になってくるので、複数台でシャーディング構成を組むことになるのでしょうが、もしデータセンターをまたいだ場合にどういった問題が起こるかなども細かく検証していく必要があると思います。時間を作って検証を進めていきたいです。

「Tech Note」ページにもMongoDBセクションを作ったので、これからコツコツ更新していきたいと思います。もし興味があれば覗いていってください。
* MongoDB – Tech Note

あわせて読む:

コメントを残す

メールアドレスが公開されることはありません。