MongoDBレプリケーションラグのトラブルシューティング:原因と解決策
MongoDBレプリカセットにおけるレプリケーションラグの診断と解決方法を学びます。このガイドでは、高い書き込み負荷、ハードウェアのボトルネック、ネットワーク問題など、一般的な原因を網羅しています。`rs.printReplicationInfo()`を使用した実用的な監視テクニックと、データ同期を維持し、すべてのデータベースノードで高可用性と読み取りの一貫性を確保するための実践的な解決策をご紹介します。
MongoDBレプリケーションラグのトラブルシューティング:原因と解決策
MongoDBのレプリケーションラグは、通常、小さな運用上の悩みから始まります。グラフが上昇し始めます。セカンダリが15秒、次に2分遅れます。誰かが読み取りが古くなっていないか尋ねます。別の誰かがノードの再起動を提案します。その前に、立ち止まって、レプリケーションのどの部分が遅れているのかを突き止めてください。
MongoDBのセカンダリは、プライマリのoplogから操作をコピーしてローカルに適用します。レプリケーションラグとは、セカンダリがプライマリほど最近に操作を適用していないことを意味します。これは、セカンダリからの読み取り、セカンダリから取得したバックアップ、分析ジョブ、フェイルオーバーに影響を与える可能性があります。また、より大きなリスクを隠している可能性もあります。セカンダリがoplogウィンドウよりも遅れている場合、oplogからまったく追いつけなくなる可能性があります。
最速のトラブルシューティングの道筋は、次の3つの質問に答えることです。
- すべてのセカンダリが遅れているのか、それとも1つだけか?
- ラグは一時的か、一定か、それとも増加しているか?
- セカンダリはまだoplogウィンドウ内にあるか?
これらの答えによって、次に何をすべきかが決まります。
推測せずにラグを測定する
mongoshで開始します:
rs.status()
プライマリを見つけ、そのoptimeDateを各セカンダリのoptimeDateと比較します。また、異常なメンバー、ハートビートメッセージ、RECOVERINGやSTARTUP2などの状態でスタックしているメンバーも確認します。
よりわかりやすいサマリーを得るには、次を実行します:
rs.printSecondaryReplicationInfo()
古い資料ではrs.printSlaveReplicationInfo()が使われていることがあります。古いシステムを保守している場合は、まだそのヘルパーが表示されることがあります。現代の用語は「secondary」です。
次に、oplogウィンドウを確認します:
rs.printReplicationInfo()
oplogウィンドウは、oplogに現在保持されている履歴の量です。セカンダリが40分遅れていて、oplogウィンドウが数日ある場合は、トラブルシューティングの余地があります。セカンダリが40分遅れていて、ピークトラフィック時にoplogウィンドウが1時間しかない場合は、再構築が必要な状況に近づいています。
単一のツールからのSecondsBehindスタイルの値だけに依存しないでください。クロックスキュー、遅延メンバー、一時的なバーストにより、1つの数値が誤解を招く可能性があります。ステータス出力を、書き込みボリューム、ディスクレイテンシ、CPU、ネットワークスループットの監視グラフと比較してください。
すべてのセカンダリが遅れている場合
すべてのセカンダリがほぼ同時に遅れる場合、原因は通常、個々のセカンダリよりも上流にあります。まずプライマリの書き込みワークロードを確認します。
一般的なトリガーは次のとおりです:
- 一括インポートまたはバックフィル。
- 大規模な
updateManyまたはdeleteMany操作。 - バックログ期間後のTTLクリーンアップ。
- 書き込みボリュームを変更したアプリケーションデプロイ。
- インデックスビルドまたはスキーマメンテナンス。
- 多数のoplogエントリを作成する小さな書き込みの突然の増加。
ラグが始まったのと同時に何が変わったかを尋ねてください。夜間ジョブが開始されたと同時にスパイクが始まる場合、それはめったにMongoDBの謎ではありません。
プライマリで、アクティブな操作を検査します:
db.currentOp({ active: true })
バッチジョブが見つかった場合は、最大速度で完了させるのではなく、スロットルすることを検討してください。たとえば、_id範囲でドキュメントを処理し、バッチ間でスリープし、ラグを監視します。これは、30分で完了することよりもレプリカセットの健全性を保つことの方が重要であるクリーンアップジョブに特に役立ちます。
持続的な書き込みボリュームがレプリカセットの処理能力を単純に超えている場合は、キャパシティまたはアーキテクチャの変更が必要です。より良いディスク、より多くのCPU、異なるインスタンスクラス、書き込みパスの最適化、またはシャーディングが正しい答えかもしれません。読み取り設定を変更しても、セットが適用できる以上の作業を生成しているプライマリは修正できません。
1つのセカンダリだけが遅れている場合
1つのセカンダリだけが遅れている場合は、通常、ローカルの問題を示しています。そのホストにログインして、基本を確認します:
iostat -xz 1
vmstat 1
top
MongoDB内で、次を使用します:
mongostat --host secondary.example.com:27017
mongotop --host secondary.example.com:27017
ディスクが一般的な原因です。プライマリよりも遅いストレージを使用しているセカンダリは、通常のトラフィックでは問題なくても、バースト時に遅れる可能性があります。クラウドボリュームもスループットまたはIOPSの上限に達する可能性があります。高い使用率、高い待機時間、キューイングがないか確認します。
CPUは、多くの更新、圧縮、暗号化、または同じメンバーへの大量のクエリトラフィックを含むワークロードの場合に重要になります。メモリプレッシャーは、セカンダリが書き込みを適用しながらホットデータとインデックスをキャッシュに保持できない場合に重要です。
また、ホストで他に何が実行されているかも確認します。バックアップ、ウイルススキャン、ファイルシステムスナップショット、ログ圧縮、レポートクエリはすべて、レプリケーションと競合する可能性があります。遅延ノードが、誰もがアドホック分析を実行する「安全な場所」でもある場合、おそらく問題を見つけたことになります。
セカンダリでの読み取りがラグを生み出す可能性がある
セカンダリ読み取りは無料ではありません。それらは、レプリケーションが必要とするのと同じキャッシュ、CPU、およびディスクを使用します。大規模なコレクションをスキャンする単一の集計は、ビジー期間中にセカンダリを遅らせるのに十分です。
長時間実行される読み取りを探します:
db.currentOp({ active: true })
アプリケーションがセカンダリに読み取りを送信する場合は、読み取り設定を確認してください。secondaryは、遅延しているメンバーに読み取りを強制する可能性があります。secondaryPreferredは、それでも古いデータを返す可能性があります。自分の書き込みを読み取る必要があるユーザーフローには、プライマリを使用します。結果整合性のある読み取りには、maxStalenessSecondsを設定して、ドライバーが遅れすぎているセカンダリを回避するようにします。
レポートワークロードには、非表示のセカンダリまたは別の分析パイプラインを検討してください。非表示のメンバーはレプリケーションを続行できますが、ドライバーは通常の読み取りのためにそれらを選択しません。そのため、適切にサイジングされていれば、バックアップや制御されたレポートジョブに適した場所になります。
Oplogサイズは回復マージンであり、速度修正ではない
oplogが小さすぎても、それ自体でラグが発生することは通常ありません。それはラグを危険にします。セカンダリが遅れ、必要なoplogエントリが上書きされた場合、正常に追いつくことができません。
oplogウィンドウは、現実的な停止およびメンテナンスシナリオよりも長くする必要があります。パッチ適用中にセカンダリが6時間オフラインになる可能性がある場合、4時間のoplogウィンドウでは不十分です。四半期ごとのインポートが数時間でoplogを使い果たす場合は、そのワークロードに合わせてサイズを調整するか、インポートの実行方法を変更します。
サポートされているバージョンでは、より大きなoplogが必要な各メンバーでreplSetResizeOplogを使用してサイズ変更します:
use admin
db.adminCommand({ replSetResizeOplog: 1, size: 20480 })
この例では、約20 GBを要求しています。マネージドプラットフォームでは、マネージド構成方法を使用します。注意深くテストされたリカバリ手順に従っている場合を除き、oplogを削除して再作成する古いアドバイスは避けてください。
oplogを拡大した後も、根本的なラグのトラブルシューティングを続けてください。oplogが大きくなると、より多くの時間が得られます。ディスクの飽和、ネットワークの制限、または過剰な書き込みバーストがなくなるわけではありません。
実際に役立つネットワークチェック
ネットワークの問題は、リモートセカンダリ、1つのアベイラビリティゾーン、または1つのデータセンターパスに影響を与える場合に発生する可能性が高くなります。簡単なことから始めます:
ping primary.example.com
traceroute primary.example.com
次に、レイテンシを超えて調べます。レプリケーションには信頼性の高いスループットが必要です。パケットロス、ファイアウォール検査、VPN制限、クロスリージョン帯域幅制限、または過負荷のネットワークインターフェイスは、pingが許容範囲に見えてもラグを生み出す可能性があります。
クロスリージョンメンバーだけが遅れている場合は、同じ書き込み負荷の下でローカルセカンダリと比較します。異なるトポロジ、より大きなリンク、またはリモートメンバーが最新の読み取りではなくディザスタリカバリ用であるという明確な期待が必要になる場合があります。
データとインデックスのドリフト
レプリカセットメンバーは同じインデックスを持つ必要があります。そうでない場合、oplogの適用が遅くなったり、失敗したりする可能性があります。これは通常、手動による変更、失敗したメンテナンス、または一貫性のないソースから復元されたメンバーが原因です。
ホットなコレクションのインデックスを比較します:
db.orders.getIndexes()
プライマリと遅延しているセカンダリで実行します。定義が異なる場合は、意図的にドリフトを修正します。大規模なインデックスを再構築すると、さらに負荷がかかる可能性があるため、注意深くスケジュールするか、差異が広範囲に及ぶ場合はクリーンなソースからメンバーを再構築します。
データの分岐はより深刻です。レプリケーションエラーにレコードの欠落や重複キーが示されている場合、ラグはもはや唯一の問題ではありません。エラーを検査し、データを比較し、テーブルレベルの修復、再同期、または完全な再構築のうち、どの方法が最も安全かを判断する必要があります。
再起動と初期同期には慎重に
遅延しているセカンダリを再起動すると、プロセスが一時的な問題の背後でスタックしている場合に役立つことがあります。これは万能の修正ではありません。メンバーがoplogウィンドウの端に近い場合、再起動により回復不能な状態に陥るのに十分な時間がかかる可能性があります。
再起動する前に、以下を確認します:
- 現在のラグ。
- 現在のoplogウィンドウ。
- メンバーが同期しているかどうか。
- 他の正常なセカンダリが存在するかどうか。
- レプリカセットがメンバーのダウンに耐えられるかどうか。
初期同期は、セカンダリが追いつけない、またはそのデータが信頼できない場合のクリーンな答えです。また、負荷も高くなります。データをコピーし、インデックスを構築し、別のメンバーからリソースを消費します。一度に1つのメンバーを再構築し、ノードの再構築中に投票構成が安全な選挙を引き続きサポートしていることを確認します。
修正を急ぐべきでない場合
制御された作業中は、ある程度のラグが予想されます。計画的なバックフィルを実行している場合、セカンダリを復元している場合、または履歴データをインポートしている場合、有用な質問は、セカンダリが許容可能な速度で追いついているかどうかです。20分間上昇し、その後着実に下降するラググラフは、介入を必要としない場合があります。毎日上昇し、ベースラインに戻らないラググラフは、介入が必要です。
この区別は重要です。なぜなら、いくつかの修正は破壊的だからです。バッチジョブを強制終了すると、アプリケーションデータが半分更新されたままになる可能性があります。セカンダリを再起動すると、キャッシュのウォーム状態が失われ、キャッチアップが遅くなる可能性があります。メンバーを再構築すると、単にバックログを適用させるよりも多くのネットワークとディスクを消費する可能性があります。
計画的なジョブの場合は、ジョブを開始する前にラグの予算を設定します。たとえば、メンテナンスのバックフィルではレポート用セカンダリに最大10分のラグが発生しても許容できるが、フェイルオーバー候補には許容できないと判断する場合があります。ジョブの実行中に、ラグ、oplogウィンドウ、および書き込みレートを監視します。ジョブが予算に近づいた場合は、一時停止するか、バッチサイズを減らします。
また、ユーザー向けのレプリカをメンテナンス用のレプリカから分離することも役立ちます。アプリケーションの読み取りに使用されるセカンダリは、バックアップに使用される非表示のメンバーよりも厳しいラグ許容度を持つ必要があります。すべてのセカンダリに異なるジョブがある場合、アラートしきい値は、セット全体に1つの数値を使用するのではなく、それらのジョブを反映する必要があります。
インシデント中に記録すべきこと
適切な証拠を保存しておけば、レプリケーションインシデントは後で理解するのがはるかに簡単になります。設定を変更する前に、以下をキャプチャします:
rs.status()
rs.conf()
rs.printReplicationInfo()
rs.printSecondaryReplicationInfo()
また、プライマリと遅延しているセカンダリのホストレベルのメトリクス(ディスクレイテンシ、CPU、メモリ、ネットワークスループット)も保存します。バッチジョブまたはデプロイが実行されていた場合は、その開始時刻とコマンドまたはリリースバージョンを記録します。
これは単なる事務処理ではありません。タイムラインがなければ、次のインシデントはゼロから始まります。タイムラインがあれば、ラグが常に特定のエクスポート、バックアップ、またはクリーンアップタスクに続くことに気付くかもしれません。これにより、漠然としたデータベースの問題が、スケジュール可能なキャパシティ問題に変わります。
実用的な修正マップ
症状を使用して次のアクションを選択します:
| 症状 | 可能性の高い領域 | 次のアクション |
|---|---|---|
| バッチジョブ中にすべてのセカンダリが遅れる | 書き込みバースト | ジョブをスロットルするか分割する |
| 1つのセカンダリが常に遅れる | ローカルリソースの問題 | ディスク、CPU、メモリ、ローカル読み取りを確認する |
| リモートメンバーでのみラグが増加する | ネットワーク/トポロジ | スループット、パケットロス、クロスリージョン設計を確認する |
| ラグがoplogウィンドウに近い | リカバリリスク | oplogを増やし、ラグの原因を減らす |
| セカンダリが古い読み取りを提供する | 読み取り設定 | 最新の読み取りにはプライマリを使用するか、maxStalenessSecondsを設定する |
| ダウンタイム後にメンバーが追いつけない | Oplog履歴の欠落 | バックアップまたは初期同期から再構築する |
優れたMongoDBレプリケーションのトラブルシューティングは、主に規律ある観察です。プライマリが過剰な作業を生成しているのか、セカンダリが適用するのが遅すぎるのか、それともそれらの間のリンクが制約されているのかを見つけてください。そして、一般的な再起動、再同期、または設定の微調整を適用する代わりに、実際にレプリケーションを制限しているものを変更します。