GoogleコンピュートエンジンでのMongoDBー -ヒントとベンチマーク評価

ここ四年間以上、Server Density社ではMongoDBをずっと運用しており、私は専用ハードウェア、仮想マシン及び複数のクラウドサービスのプロバイダー間で展開することができました。
専用のサーバーは一番いい環境と言えます。それは特にCPUとディスクi/oのホストのコンテンションの問題があるためです。しかしながら、Googleはコンピュートエンジンの製品の一貫性及びパフォーマンスを誇っており、特に高度の帯域幅調整により複雑な問題を処理できるとしています。
そこで、私はGoogleコンピュートエンジンでMangoDBがどのようなパフォーマンスを見せるかについて検証することしました。
書き込み確認(Write Concern)のテスト-パフォーマンスと耐久性
MongoDBの書き込み確認(Write Concern)の問題は、以前から物議を醸してきました。元来、Mongoは耐久性を犠牲にして非常に高度な書き込みスループットを得るために設計されていますが、この件に関しては十分に立証されていませんでした。しかしそのデフォルトはかなり前に変更され、現在では、書き込みに関しては受け入れられたことを確認応答(Acknowledgement)をする上に、速度か耐久性を調整できる柔軟性があります。
私は書き込み確認(Write Concern)のテストをして、どの程度の応答時間を期待できるか確認してみたいと思います。:
未確認(Unacknowledged): w = 0 AND j = 0
このやり方では、ドライバーはサーバーに書き込みをしたか確認をしません。そのため、うまく書き込めたかは不明で、そのネットワークエラーの発見についても不明確です。
確認済み(Acknowledged): w = 1 AND j = 0 (デフォルト設定)
このやり方では、うまく書き込みができたか確認できますが、実際に書き込みがされたかというしるしはありません。しかしこれにより大部分のエラーを見つけられます。例えば、解析エラー、ネットワークエラーなどです。
実行記録の書き込み(Journaled): w = 1 AND j = 1
このやり方ではプライマリのレプリカセットのメンバーによるジャーナルへの書き込みと確認されるまで、書き込みを待たせることになります。そのため、単一サーバーとしての耐久性はあっても、データが他のクラスターにレプリケーションされたということを保証するものではありません。理論的には、データセンターの障害や書き込みの失敗の可能性が考えられます。
レプリカ確認(Replica acknowledged): w = 2 AND j = 0
このテストでは、データの書き込みがレプリカセットによって確認されるまでどのくらい時間がかかるか、またレプリカセットの少なくとも1つのメンバーが確認されるまでにどのくらいの時間がかかるかが分かります。また、2つのサーバー間での耐久性が生まれます。しかし、理論的に、その書き込みは両方とも失敗する可能性もあります。なぜならば、ジャーナルへの書き込みをチェックはしてないからです。
レプリカ確認(Replica acknowledged) と 実行記録の書き込み(Journaled): w = 2 AND j = 1
このやり方では、データはプライマリに送られ、そのレプリカセットの中の少なくとも一つのメンバーによる確認を保証できます。
レプリカ確認(Replica acknowledged)と過半数確認: w = majority AND j = 0
複数のデータセンター環境では、ユーザーは、データが安全に複製されたか知りたいはずです。この majority
のキーワードにより、書き込みがレプリカセットの過半数メンバーにより確認されたことを保証します。もしユーザーがそのセットを均一的にデータセンターに配備できた場合には、データーは安全に複数の場所に保管されていることを確認できます。
レプリカ確認(Replica acknowledged)と過半数確認と実行記録の書き込み: w = majority AND j = 1
これはおそらくパラノイドモードの最たるもので、書き込みがプライマリでしっかり確認されて、過半数のノードに複製されたことが分かります。
環境設定
レプリカセット
実世界では、アプリケーションはレプリカセットを利用して、複数のデータセンター間での冗長性とフェイルオーバー機能を持たせています。このことを正確にテストするために、テスト環境では2つのゾーンに渡る4つのデータノードを含めました。そのうち2つは us-central1-a
ゾーンで、他の2つがus-central1-b
ゾーンです。
実際の配備においては、障害の時にそのセットを維持できるよう過半数のセットを持っていなければいけません。そのためアービタとして5つ目のノードを他のデータセンターに配備します。なお、ここでは話を単純にするために、私は試しませんでした。
Googleコンピュートエンジン
私はn1-standard-2
(2 vCPUs と 7.5GB RAM)とn1-highmem-8
(8 vCPUs と 52GB RAM)イスタンスタイプに backports-debian-7-wheezy-v20140318
OSイメージを追加してテストしました。
インスタンスのCPUコアの数により、i/oパフォーマンスも影響を受けます。最高のパフォーマンスの実現のためには、提供される全部のメモリーを使わないとしても、4つか8つのコアのインスタンスタイプを使用しなければなりません。
さらにそのデフォルトロケールがまだ設定されていないところでの
GCE Debianイメージにはバグがあることにも留意ください。このことがDebianパッケージからMongoDBを正常にスタートさせることを阻んでいます。その回避策は以下のようにデフォルトを設定することです。
sudo locale-gen en_US.UTF-8
sudo dpkg-reconfigure locales
Google永続ディスク
Google永続ディスクのパフォーマンス特徴とIOPSが、ボリュームのサイズとどのようにリニアに変動するか理解することは重要です。以下、ここでの重要なポイントを記します。
- 少なくとも別々の永続ディスク上にMongoDB dbpathをマウントする必要があります。これはすべてのコンピュートエンジンインスタンスのデフォルトルートボリュームが小さいために、低いパフォーマンスしか期待できないためです。仮にOSバーストは許容するとしても、通常持続的な使用要件のあるMongoDBでは十分ではありません
- directoryperdb を使用して、それぞれのデータベースに永続ディスクボリュームを付与します。これにより、パフォーマンスとコストを最適化できます。さらに自身のデータ増加に対応する場合やIOPsのパフォーマンスの利点を得るためにボリュームを修正できます。
- directoryperdbがない場合でも、は ジャーナルはいつも自身のディレクトリにあるので、別のボリュームにジャーナルを書き込むことは可能です。もし、別のボリュームにデータベースを入れないとしても、パフォーマンスの改善はx3までと顕著なので、ジャーナルを自身の永続ディスクに分離しておく価値はあります。 (結果は以下を参照).
- もし、自分のデータベース(もしくはジャーナルだけでも)を他のボリュームに分離したら、バックアップ用のスナップショットは利用できません。これは複数のボリュームでのスナップショットは、必ずしも同時に起きないので、一貫性がないためです。その代わりに、mogodを終了して(あるいはfsyncロックをして)、すべてのディスクのスナップショットを取らねばなりません。
ジャーナルの書き込みは数GBのスペースだけしか使用しないので、必要なボリームは相当少ないかもしれません。しかしながら、利用可能なIOPsはボリュームサイズとともに上がるので、永続ディスクのボリュームを小さく割り当てることはパフォーマンスの低下につながります。ジャーナルの書き込みには、少なくとも200GBのボリュームを選択して下さい。
私はパフォーマンスの特徴の違いを確認するために、様々なディスク設定で何度もテストをしました。
- 1.デフォルト10GBシステムボリュームのみで追加のディスク、すなわちdbpathは無し
- 2.
dbpath
用の、200GBの永続ディスクを加える - 3.
dbpath
用の200GBの永続ディスク、及びジャーナル書き込み専用の200GBの永続ディスクを加える
テスト方法
私はコレクションに静的ドキュメントを挿入するために、Pythonの短いスクリプトを書きました。これは1000回実行されて、3回繰り返されました。このテストを完了するため、Pythonのtimeitライブラリーが使用されましたが、この資料では3回のテストサイクルの平均/標準偏差は有効ではないと示されていることから、ここでは最速の時間が採られました。
結果 ― Google コンピュートエンジンでのMongoDBのパフォーマンス
n1-standard-2
n1-highmem-8
単一の永続ディスクボリュームを使用する場合には、耐久性のオプションを上げるまではパフォーマンスにあまり違いはありません。これは、確認(acknowledged)または未確認(Unacknowledge)の書き込みはメモリに行くだけだからです。書き込み確認(Write Concern)のオプションを増やすとディスクのパフォーマンスは制限されますので、ジャーナルの書き込みを別のボリュームに分離することで大きな違いが生じることは明白です。
n1-水準-2
の2コアと比較した場合、8コアの大きなn1-highmem-8
のインスタンスタイプは、実際の差は小さいものの、その数字からパフォーマンスが向上していることがこの図から明らかです。 実際の差はかなり小さいとしても、実世界では役に立ちます。
重要なポイントは耐久性がアップすると、パフォーマンスは低下するということです。それはトレードオフであると言えます。耐久性をもたせながら最高のパフォーマンスを得るには、コンピュートエンジンでより高いスペックのインスタンスタイプを選び、データベース/ジャーナルごとに別の大型の永続ディスクボリュームを利用するということです。