最近「注目のNoSQLデータベースMongoDB!」みたいな持ち上げられ方をしているMongoDB。確かにSQLライクな複合構文を持ち、自動的なデータ分散のShardingなどを備えていてモダンな感じ。しかし.... とにかく不安定で困る....
以前、東京キャビネットを使っていた時も散々文句を言っていたけど、今考えればこいつは素直な部類であった。
例えば、多数のインデックスカラムを持つテーブルに対して、大量のデータを登録した場合:
お次は検索。全データをサーチするような用途ではどちらもカーソルを使うのだが:
最後はサーバ同士のレプリケーション(いわゆるプライマリー/セカンダリーというやつだ)性能:
............
....
本当に簡単に諦めて、しかもresultとってきても原因がわからないので困る。さらに、MongoDBでは、Shardingで複数サーバにデータが分散している場合 同じレコードが2,3個帰ってくる ことさえある。さらに登録したデータにensureIndexして、 すぐ検索できると思ったら大間違いで MongoDB が暇になったらインデックス貼ってくれるくらいの遅延をする。
もちろん....アプリ(クライアント)側でできることは沢山ある。追加時は{safe:1}をつけたり、find()の結果をみて検索処理を分割したり、そもそも巨大クエリーは投げないように工夫したり、snapshot()で重複データを除いたりするノウハウはあるんだよ。
でも.....半年くらい使ってきたけど ちょっとプロダクトレベルに達していない 印象が。2.2.0(stable)とか書いてあっても全然安定版じゃない。ふつーにデータ登録してふつーに検索(この場合のふつーはMySQLみたいな豪勢なものの話じゃなくてTokyoCabinetレベル)することが、できないよ。
補足として MongoDBを使うなという議論があったこともつけ加えておく。けど、 採用を検討してる人はもう一度考えなおした方がいいかも。
しかしこれらを すべて差し引いたとしても「許せない」ことがある ....それは mongos(プロキシー)が突然死する ことだ。たぶん実験室レベルでサーバ1台でやってるときは絶対気づかないだろう。Shadringも使わないだろうし。でも通信や負荷が少し不安定な環境で実運用に近い形でやってみれば、mongosのフリーズは10回や20回では収まらないことはわかるはず(同志いませんかね?)
しつこいが、何かクリティカルなことをしてるわけじゃなくて、単純なドキュメントを挿入してるだけなんだ。でもmongosは応答を返さなくなる。ポートlistenしたままプロセスが残るとか超極悪である。
@400000005074f7cb3b3478a4 *** glibc detected *** /usr/local/bin/mongos: free(): invalid pointer: 0x0000000000b183e0 *** @400000005074f7cb3b34f5a4 ======= Backtrace: ========= @400000005074f7cb3b35b50c /lib/libc.so.6(+0x71bd6)[0x7f558afe5bd6] @400000005074f7cb3b36591c /lib/libc.so.6(cfree+0x6c)[0x7f558afea94c] @400000005074f7cb3b382224 /usr/local/bin/mongos(_ZN5mongo13BackgroundJob7jobBodyEN5boost10shared_ptrINS0_9JobStatusEEE+0x1b9)[0x525119] @400000005074f7cb3b39e35c /usr/local/bin/mongos(_ZN5boost6detail11thread_dataINS_3_bi6bind_tIvNS_4_mfi3mf1IvN5mongo13BackgroundJobENS_10shared_ptrINS7_9JobStatusEEEEENS2_5list2INS2_5valueIPS7_EENSD_ISA_EEEEEEE3runEv+0x74)[0x527394] @400000005074f7cb3b3c3904 /usr/local/bin/mongos(thread_proxy+0x80)[0x806720] @400000005074f7cb3b3c6014 /lib/libpthread.so.0(+0x68ca)[0x7f558ba888ca] @400000005074f7cb3b3d2f1c /lib/libc.so.6(clone+0x6d)[0x7f558b04392d]
落ちた時のトレースとってみてもShardingのロック周辺に、何かバグがあると思うんだけどなー....俺も追いきれてない。
実際にMongoDBを大規模運用してるサイバーエージェントとかどうしてんでしょうね......本当に金払ってもいいから聞きたいわ。それ以前にこんなおっかなビックリしながらデータベース使いたくないけど。
こんな状態なので、当然MongoDBを監視するということを考える必要がある。しかし上記で散々グダグダ書いていたmongosはプロキシなのでほとんど何のデータも持たない。なのでこいつ自体はプロセスをmongostatか何かで監視して応答なくなったらKILLするスクリプトを書けばいい。問題は配下のconfig serverやsharding server。こいつらは状態監視する以外に特段の方策がない。
そこでサーバ監視ではお馴染みのMuninのプラグインを書きました。 実は本家にもプラグインはあるのだが、本家とコレとは 監視する箇所 が違うのである。
本家はオーソドックスな発行命令数が採れるだけである。 でも個人的なたった半年の経験からして 各コマンドの「重さ」と「命令数」 にはあまり強い相関がない気がする。 補足資料として Akihiro Kuwanさんのアレをアレする をご覧ください。
俺的にはMongoDBが落ちる時は mongostatでいうlockedが長時間高くなった 直後に落ちてる気がしているのでmongostatを監視するMuninプラグインを書きました。ついでにデータベースのモードがプライマリーかセカンダリーかリカバリーか不定かもグラフ表示できるようにした。これは便利!!
まあ、mongostatレベルでもたまにとんでもない値が出るのであくまで参考までに(俺のせーじゃないよ)。しかし...公式ツールでパーセンテージのカラムに6000とか出るのは正直どうなんだ???誰もデバッグしてねーだろ....これがMongoDBの正常なのけ。
mongostat_.txtをコピーして...
とかして拡張子をとってコピーしてください(アンダーバーは消さないでください)。
使う時はMongoDBのポート番号をつけてシンボリックリンクをはってください。つけないとデフォルトポート(27017)が使われます。
# ln -s /usr/share/munin/plugins/mongostat_ \ /etc/munin/plugins/mongostat_5001
しかし、説明かいてて思ったけど、もしかして1サーバに多数のmongod起動してること自体が問題なのか?ちょっと鬱になってきた。