中年engineerの独り言 - crumbjp

LinuxとApacheの憂鬱

MongoDB の チューニンガソン環境を作った。

例のGoogle compute engine 60日トライアル の$300 分をどう使おうか・・・と考えていたのだが、MongoDBのチューニンガソンに使えるんじゃないか!?と思って週末に一気に作ってみた。

mongo-tuningason.crumb.jp"

いきなり超負荷を掛けると、色々問題が起きるので、Stage1 ~ 4 まで別けて、ある程度チューニングが進んでから、だんだん負荷が掛かる構造にした。

stage1 5秒以内に一連のクエリーが完了すること。プロファイルの取り方と基本的なindex知識
stage2 5秒以内に一連のクエリーが完了すること。複雑なindexが張れるか?
stage3 2~3秒の間で難易度を調整中。かなり突っ込んだindexを張れないとクリア出来ない
stage4 最終ステージ。負荷が一気に増え、クリアではなくスコア(qps)での競争。MongoDB周りならなんでもあり。
stage5 構想段階。アプリ側も含めたチューン

恐らくstage3 まで行く人は既に普通には困らないだけの知識を持っているし、stage3 をクリアする人はマスターレベルだと思われる。

一旦、何人かにβテストの挑戦をして貰いたい。
興味がある人はfacebookで声を掛けて欲しい!!!!
SSHが出来るホストをお渡しして好きにチューンして貰う感じになります~

mongosが腐る・・・

mongosの後ろのshardでstepdownが起きたときにmongosが追随せずに以降のクエリーが全て刺さり続けることがある。
こうなるともう自動で復活はしないようだ。


すべてのmongosが腐る訳ではなく、stepdown時に高負荷だったmongosが腐る傾向にある。
shardConnPoolStats コマンドではmasterが変わった事が認識できているので、何かしらのrace condition のバグがあると思われる。

少なくとも2.6系,3.0系で起きる。3.2系は不明だが恐らく起きるだろう。
本番クラスの負荷がかからないと再現しないので原因特定もかなり覚悟が要る。。。


とりあえず、監視スクリプト書いて自動再起動させる事にするが。。

jiraにも上がってなさそうだし、こんなバグ誰も気づかないんだろうか・・・

MongoDBクラスタ間の同期

node-mongosync

https://www.npmjs.com/package/node-mongosync

ステージング環境へのデータ同期や、MongoDB引っ越しの際に便利。
そうそう引っ越さないけど・・

以前 mongoshellで実装したものの焼き直しだ。
node-native-driverでは、tailable cursor の closeが検知出来たり、oplogの読み込みと同期先への書き込みが非同期に同時進行出来るため、性能的に有利だった。
反面CPU処理能力は若干劣るため、フックを差し込む機構は今の所諦めている。

あとnpmを使えるので導入が楽だ。
これが一番大きな理由かもしれない。

npmjs のREADME.md の表示がやたら汚いのがつらい・・・ githubの方みてね・・・

『もう二度と、絶対にMongoDBを使うべきじゃない理由』というのがあるらしい

記事

https://fa-works.com/blog/why-you-should-never-ever-ever-use-mongodb

なかなか香しいな。
というよりコイツ他のブログも結構ヒドイw
とりあえず不満をぶちまけるタイプのようだ。

で、、事の本質はプロダクトの設計がちゃんと出来ない人はどんな場合でも選択を間違えるという事だ。

実際MongoDBは使いどころがかなり限られている。
MongoDBが得意なケース"以外"では絶対MongoDBを使ってはならない
 WriteConcernはあくまでAdditionalな機能であって本来やりたい事では無い。(RDBMSなら2フェーズコミットだぜ?)
 実際、最近追加されたReadConcernもヒドイ実装である。

殆どのケースではORMが完備してるフレームとMySQLを使うのが鉄板なのは間違いない。

じゃあ具体的にいつ使うのか?というと

Dirty read が許され、且つ、Readが支配的な場合

だ。

性能面に関しては、スタンドアローン型のストレージに劣る。
これはレプリケーション機構があるので(例えその機能を切ったとしても)そのオーバーヘッドに拠るものが大きい。但し実装も良くない。


しかしPostgreSQLねぇ・・・運用するんだ・・・がんばれ〜
大丈夫!イザとなったらRedShiftがあるさ。。

MongoDB3.2 readConcernの挙動について

実装

mongosの場合はもうちょっと複雑になるが、レプリカセットの場合はこの辺に実装があるようだ

=== /db/repl/replication_coordinator_impl.cpp ===
    auto loopCondition = [this, isMajorityReadConcern, targetOpTime] {
        return isMajorityReadConcern
            ? !_currentCommittedSnapshot || targetOpTime > _currentCommittedSnapshot->opTime
            : targetOpTime > _getMyLastOptime_inlock();
    };

    while (loopCondition()) {
        Status interruptedStatus = txn->checkForInterruptNoAssert();
        if (!interruptedStatus.isOK()) {
            return ReadConcernResponse(interruptedStatus, Milliseconds(timer.millis()));
        }

        if (_inShutdown) {
            return ReadConcernResponse(Status(ErrorCodes::ShutdownInProgress, "shutting down"),
                                       Milliseconds(timer.millis()));
        }

        stdx::condition_variable condVar;
        WriteConcernOptions writeConcern;
        writeConcern.wMode = WriteConcernOptions::kMajority;

        WaiterInfo waitInfo(isMajorityReadConcern ? &_replicationWaiterList : &_opTimeWaiterList,
                            txn->getOpID(),
                            &targetOpTime,
                            isMajorityReadConcern ? &writeConcern : nullptr,
                            &condVar);

        if (CurOp::get(txn)->isMaxTimeSet()) {
            condVar.wait_for(lock, Microseconds(txn->getRemainingMaxTimeMicros()));
        } else {
            condVar.wait(lock);
        }
    }

どうもmajorityになるまで単純にwhile ループで待ってるようだが
こんな乱暴な事をすると、簡単にDOSになりそうだが、どうなんだろう?

仮に 1秒位遅延が起きた時に、5000 queryも readConcern: majority でクエリーすると何が起きるか?
余裕でリクエストを処理するスレッドを潰されてしまいそうな気がする。

だれか一緒に検証してくれる人いませんかね??

MongoDB3.2 ReleaseNote所感

そろそろ3.2も手を付けようと思うので、検証がてらつらつらと。。

リリースノート

https://docs.mongodb.org/manual/release-notes/3.2/

非常に丁寧な日本語訳があるので、こちらもどうぞ
http://qiita.com/fetaro/items/cd570d70623b58b5deef

WiredTiger as Default

まあ規定路線なので、特に気にする必要なし。

Replication Election Enhancements

Primaryが落ちた時の検知が早くなった。
どういうシチュエーションでどの位早くなるのかはまだ検証してない。
少なくとも今迄の落ち認定10秒をカスタマイズ可能になった。
その他色々timeout値が弄れるようになった様だが、これはまだ実験段階なんだろう。と読む事もできる。
要注目

Sharded Cluster Enhancements

configサーバが独自2-phase-commit ではなく、普通のReplicaSet で組めるようになった。
今迄は3ノード限定。1ノードでも落ちたら(shard周りの)更新不能だったが、可用性が格段に上がったということだ。

readConcern

書き込み時の保証であるwriteConcernだけでなく、読み込み時の保証が取れるようになった。
ただ、こんな事をしてどうやって性能を上げるつもりなのか解らない
これはコードを読む必要がありそう。

Partial Indexes

全ドキュメントにインデックスを張らない随分とチャレンジングな機能。
正にドキュメントベース独特の悩みの具現化だな。
これは機能としては素晴らしいがアプリ側がかなり大変そうな気がする。
限定した使い方なら非常によさそう。

例えば、{ active: true } のドキュメントだけ indexに含める。
といった使い方が良い。
この様なケースならば、Oracleのbitmap indexより効率的かもしれない。

Document Validation

謎機能!!
ドキュメントベースのDBでこれをやるか!!
只でさえフィールドがnull、undefinedで、クエリー周りの混乱があるのにこういう事すると更に拍車をかけそう。
沢山失敗例がネットに溢れると思われる

Aggregation Framework Enhancements

色々足されているが、 まずは$lookupだけ気にしていれば良い。
他は細々しているが

  • 演算系のオペレータは嬉しい。
  • $unwind が配列以外を受け付けなくなったのがちょっと痛い
  • covered indexが有効になったので軽くなるケースも若干ある。(むしろ$lookupで有効ならば非常に嬉しい機能)
MongoDB Tools Enhancements

mongodump / mongorestore が圧縮転送可能になったので、ありがちな、mongodump & s3 に放り込む。といったバックアップが早くなるのが嬉しい。

Text Search Enhancements

例によって無視

New Storage Engines

気にする必要なし

General Enhancements

ビット演算オペレータは使えるケースがあるかな?無いよな・・・
ドキュメントベース使っててフィールド分けない理由が無いんだけど・・・

SpiderMonkey JavaScript Engine

なぜだ!!

WiredTiger and fsyncLock

以前にも触れたが、やっとまともにバックアップが取れるようになる。


あとは良いや。

3.2は新バージョンというより3.0 系の決定版のような位置づけっぽいですね。