MongoDB
MongoDBDay 9

CappedCollectionのススメ

More than 5 years have passed since last update.

Gunosyではログ解析周りや推薦エンジンでMongoDBを使っています。

ちょっと前に勉強会でMongoDBのMapReduceでログ解析やってるよって話をしたところ、


  • MongoDBのMapReduceって遅くない?

  • データ量増えるとリソース相当使わない?

とのツッコミを頂きました。

指摘自体は正しいと思っていて、データ増えるとすぐ計算時間やサーバのリソース使用量が大変なことになります。

それを避けつつ、節約して運用するためにGunosyのログ解析周りではCapped Collectionを使ってます。


Capped Collectionって?

ご存知の方も多いと思いますが、念のため本家から引用すると、

Capped collections are fixed-size collections that support high-throughput operations that insert, retrieve, and delete documents based on insertion order.

要はサイズ固定で高速に使えるcollectionだと思っていただければ結構です。

長所


  • サイズ固定なので不用意にリソースを使用し過ぎることがない

  • 割と高速

短所


  • 後からcapサイズが変更しづらい。(できなくもないです)


Capped Collectionを利用する場合は以下のコマンドで確認できます。

// 新しくコレクションを作る場合

db.createCollection( "mycol", { capped: true, size: 100000 } )

// すでにコレクションが存在する場合
db.runCommand({"convertToCapped": "mycoll", size: 100000});

コレクションのstatsを見れば、cappedになっているか確認できます。

> db.mycol.stats()

{
"ns" : "test.mycol",
"count" : 0,
"size" : 0,
"storageSize" : 12288,
"numExtents" : 1,
"nindexes" : 1,
"lastExtentSize" : 12288,
"paddingFactor" : 1,
"systemFlags" : 1,
"userFlags" : 0,
"totalIndexSize" : 8176,
"indexSizes" : {
"_id_" : 8176
},
"capped" : true,
"max" : NumberLong("9223372036854775807"),
"ok" : 1
}


どう使っているか

以下の2点に注意してログ解析部分に使っています。


  • 解析項目に合わせてログフォーマットを毎度用意している

  • 計測に必要なログの保存日数に合わせてCapサイズを決定している。

解析では生のアクセスログを殆ど使っていません。

ログ解析もサーバのコードも同じ人間が担当するので、解析項目に合わせて新しく必要最低限のデータのみ送信するロガーを適宜実装して、同時にログ集計用スクリプトも用意する形になっています。(このへんはFluentd使っている)

アクセスログだとどうしてもpathだとかリクエストのパラメタだとかが入ってしまうので、collectionサイズが肥大化してしまいますが、解析項目に対して本当に必要なデータのみMongoDBへ保存するとそれほど容量は使いません。

ちなみに生のアクセスログも一応MongoDBへCapかけて保存していますが、ほとんどはS3へ保存→Redshiftへ、という流れになってます。

この運用だと、解析自体もそれほど大きなリソースを使わず今のところ維持できています。


この運用の欠点

長期間のデータを後から解析したくなったときは、Collection内にそれほど長期のデータが保存できていないので、ここは社内だとRedShiftを利用しています。


まとめ

Capped Collectionをうまく使うとそれなりの規模でもリソースを節約しながら性能を維持してMongoDBを運用できますよという話。