web-dev-qa-db-ja.com

Mongodbは、レプリカの再同期中に消費しすぎるRAM

2つのデータノードと1つのアービターを持つmongodbクラスターがあります。私はすべてのCentOS VMにmongodb 4.0.7を使用しています。

数日前に、私のサーバーの1つ(これをdata-2と呼びます)で致命的なクラッシュが発生し、データの完全な再同期を要​​求しました。 data-2でmongodbを再起動した後、再同期が開始されました。しかしその直後、RAM data-1(primary)の使用がスカイロックになり始めました。

data-1 memory consumption rises continuously

ただし、データ2では、メモリ消費量はほぼ一定でした。

data-2 memory consumption remains the same

通常の使用時間中のメモリ消費は、再同期中はdata-2に近いままです。

数時間後、最悪のシナリオが起こり、最後の残りのデータホルダー(data-1)は、ram + swap(〜50GB)全体を使用した後、カーネルによってOOMを強制終了しました。少しの労力でdata-1をプライマリとして復元できましたが、再同期を開始しようとするたびに、同じことが再度発生します。

この動作は、再同期中の実際のデータベースの使用とは関係がないようです。 (再同期のためにprod dbを停止することは間違いなくノーゴーです)。

合計データサイズは最大500GB、最大データベースは最大480GB、最大300のコレクション。

今私の質問:

  • 再同期中にその多くのメモリを使用するものは何ですか?
  • メモリ消費を効果的に分析するにはどうすればよいですか?
  • 再同期が原因でプライマリが停止しないようにするにはどうすればよいですか?
2
ST-DDT

再同期中にその多くのメモリを使用するものは何ですか?

再同期時にメモリを使用するものはたくさんあります。Mr. SpiXelは明確に定義しているため here WiredTiger キャッシュ設定 は、によって直接使用されるメモリのサイズのみを制御しますWiredTigerストレージエンジン(mongodが使用する合計メモリではありません)。 MongoDB/WiredTiger構成では、次のような他の多くのものがメモリを潜在的に使用しています。

  • WiredTigerはディスクストレージを圧縮しますが、メモリ内のデータは圧縮されません。
  • WiredTigerはデフォルトでは、コミットごとにデータをfsyncしません
  • WiredTigerはキャッシュに複数のバージョンのレコードを保持します
  • WiredTigerはデータのチェックサムをキャッシュに保持します
  • MongoDB自体は、開いている接続、集計、サーバーサイドコードなどを処理するためにメモリを消費します。

WiredTigerがすべてのデータに使用する内部キャッシュの最大サイズ。

バージョン3.4で変更:値の範囲は256MBから10TBで、フロートにすることができます。また、デフォルト値も変更されています。

3.4以降、WiredTiger internal cacheはデフォルトで次のいずれか大きい方を使用します。

50% of (RAM - 1 GB), or
256 MB.

、合計4GBのRAMのシステムでは、WiredTigerキャッシュは1.5GBのRAM(0.5 *(4 GB-1 GB)= 1.5 GB)。逆に、合計が1.25 GBのRAMを搭載したシステムでは、合計RAMの半分から1ギガバイト(0.5 *(1.25 GB-1 GB )= 128 MB <256 MB)。

メモリ消費を効果的に分析するにはどうすればよいですか?

MongoDBブログ here の一部(@CASEY DUNHAM)によると、MongoDBのパフォーマンスは、システムアクティビティの多くの領域を網羅する大きなトピックです。デフォルトでは、MongoDBは、WiredTigerデータキャッシュに使用可能なメモリの50パーセントを予約します。このキャッシュのサイズは、WiredTigerが適切に実行されるようにするために重要です。デフォルトから変更する必要があるかどうかを確認してみる価値があります。経験則として、キャッシュのサイズは、アプリケーションのワーキングセット全体を保持するのに十分な大きさである必要があります。

それを変更するかどうかはどうやってわかりますか? キャッシュ使用量 統計を確認します。

> db.serverStatus().wiredTiger.cache
{
    "tracked dirty bytes in the cache" : <num>,
    "tracked bytes belonging to internal pages in the cache" : <num>,
    "bytes currently in the cache" : <num>,
    "tracked bytes belonging to leaf pages in the cache" : <num>,
    "maximum bytes configured" : <num>,
    "tracked bytes belonging to overflow pages in the cache" : <num>,
    "bytes read into cache" : <num>,
    "bytes written from cache" : <num>,
    "pages evicted by application threads" : <num>,
    "checkpoint blocked page eviction" : <num>,
    "unmodified pages evicted" : <num>,
    "page split during eviction deepened the tree" : <num>,
    "modified pages evicted" : <num>,
    "pages selected for eviction unable to be evicted" : <num>,
    "pages evicted because they exceeded the in-memory maximum" : <num>,
    "pages evicted because they had chains of deleted items" : <num>,
    "failed eviction of pages that exceeded the in-memory maximum" : <num>,
    "hazard pointer blocked page eviction" : <num>,
    "internal pages evicted" : <num>,
    "maximum page size at eviction" : <num>,
    "eviction server candidate queue empty when topping up" : <num>,
    "eviction server candidate queue not empty when topping up" : <num>,
    "eviction server evicting pages" : <num>,
    "eviction server populating queue, but not evicting pages" : <num>,
    "eviction server unable to reach eviction goal" : <num>,
    "internal pages split during eviction" : <num>,
    "leaf pages split during eviction" : <num>,
    "pages walked for eviction" : <num>,
    "eviction worker thread evicting pages" : <num>,
    "in-memory page splits" : <num>,
    "in-memory page passed criteria to be split" : <num>,
    "lookaside table insert calls" : <num>,
    "lookaside table remove calls" : <num>,
    "percentage overhead" : <num>,
    "tracked dirty pages in the cache" : <num>,
    "pages currently held in the cache" : <num>,
    "pages read into cache" : <num>,
    "pages read into cache requiring lookaside entries" : <num>,
    "pages written from cache" : <num>,
    "page written requiring lookaside records" : <num>,
    "pages written requiring in-memory restoration" : <num>
}

ここには多くのデータがありますが、次のフィールドに集中できます。

  • wiredTiger.cache.maximum bytes configured:これは最大キャッシュサイズです。
  • wiredTiger.cache.bytes現在キャッシュにある–これは現在キャッシュにあるデータのサイズです。これはmaximum bytes configuredを超えてはなりません。
  • wiredTiger.cache.trackedキャッシュ内のダーティバイト–これは、キャッシュ内のダーティデータのサイズです。この値は、現在キャッシュ値にあるバイト未満である必要があります。

これらの値を見て、インスタンスのキャッシュのサイズを増やす必要があるかどうかを判断できます。さらに、読み取りが多いアプリケーションのwiredTiger.cache.bytes read into cache値を確認できます。この値が一貫して高い場合は、キャッシュサイズを大きくすると、全体的な読み取りパフォーマンスが向上する可能性があります。

再同期が原因でプライマリが停止しないようにするにはどうすればよいですか?

MongoDBブログのドキュメントのとおり here 主にアクセスできなくなる状況が発生する可能性があります。プライマリがセットの他のメンバーと10 secondsを超えて通信しない場合、適格なセカンダリは、それ自体を選出するための選挙を開催します新しいプライマリ。選挙を開催し、メンバーの投票の過半数を受け取った最初のセカンダリがプライマリになります。タイミングは異なりますが、failoverプロセスは通常1分以内に完了します。たとえば、レプリカセットのメンバーがプライマリにアクセスできないことを宣言するには、10-30 secondsが必要な場合があります。残りのセカンダリの1つは、自分をnew primaryとして選出する選挙を保持しています。選挙自体は別の10-30 secondsをとることがあります。選択が行われている間、レプリカセットにはプライマリがなく、書き込みを受け入れることができず、残りのすべてのメンバーは読み取り専用になります。

さらにあなたの参照 herehere および here

1

したがって、セカンダリメンバーが古くなり、プライマリoplogおよびoplogエントリの上書きよりもはるかに遅れると、mongodはデータを削除して初期同期を実行することにより、古いメンバーを完全に再同期します。

MongoDBのドキュメントに従って、

最初の同期を実行すると、MongoDBは次のことを行います。

ローカルデータベースを除くすべてのデータベースを複製します。クローンを作成するために、mongodは各ソースデータベースのすべてのコレクションをスキャンし、すべてのデータをこれらのコレクションの独自のコピーに挿入します。

バージョン3.4で変更:ドキュメントが各コレクションにコピーされるときに、初期同期によりすべてのコレクションインデックスが作成されます。 MongoDBの以前のバージョンでは、この段階では_idインデックスのみが作成されました。

バージョン3.4で変更:初期同期は、データのコピー中に新しく追加されたoplogレコードをプルします。このデータコピーステージの間、ターゲットメンバーがローカルデータベースにこれらのoplogレコードを一時的に格納するのに十分なディスク領域があることを確認してください。

すべての変更をデータセットに適用します。ソースからのoplogを使用して、mongodはレプリカセットの現在の状態を反映するようにデータセットを更新します。

最初の同期が完了すると、メンバーはSTARTUP2からSECONDARYに移行します。

あなたのケースでは、プライマリはそれが過剰に使用されている300のコレクションをコーンする必要があります。また、mongodbは次の再同期オプションを提案しています。

MongoDBには、初期同期を実行するための2つのオプションがあります。

空のデータディレクトリでmongodを再起動し、MongoDBの通常の初期同期機能でデータを復元します。これはより単純なオプションですが、データの置換に時間がかかる場合があります。

メンバーの自動同期を参照してください。

レプリカセットの別のメンバーからの最近のデータディレクトリのコピーでマシンを再起動します。この手順では、データをより迅速に置き換えることができますが、より多くの手動の手順が必要です。

別のメンバーからのデータファイルのコピーによる同期 を参照してください。

0
Mani