Skip to content

Instantly share code, notes, and snippets.

@YTakahashii
Created September 18, 2021 07:20
Show Gist options
  • Save YTakahashii/e92ed727dbe6de9eaa62b2c9c22eb650 to your computer and use it in GitHub Desktop.
Save YTakahashii/e92ed727dbe6de9eaa62b2c9c22eb650 to your computer and use it in GitHub Desktop.

Replication

https://docs.mongodb.com/manual/replication/

MongoDB のレプリカセットとは、同じデータセットを維持する mongod プロセスのグループです。レプリカセットは冗長性と高可用性を提供し、すべての本番環境での展開の基本となります。このセクションでは、MongoDBのレプリケーションを紹介するとともに、レプリカセットのコンポーネントやアーキテクチャについても説明します。また、レプリカセットに関連する一般的なタスクのチュートリアルも紹介します。

Redundancy and Data Availability冗長性とデータ可用性

レプリケーションは冗長性を提供し、データの可用性を高めます。レプリケーションは、異なるデータベースサーバー上にデータの複数のコピーを持つことで、単一のデータベースサーバーの損失に対するレベルのフォールトトレランスを提供します。

場合によっては、クライアントが読み取り操作を別のサーバーに送ることができるため、レプリケーションによって読み取り容量を増やすことができます。異なるデータセンターにデータのコピーを維持することで、分散型アプリケーションのデータの局所性と可用性を高めることができます。また、ディザスタリカバリ、レポーティング、バックアップなど、専用の目的で追加のコピーを維持することもできます。

Replication in MongoDB

レプリカセットとは、同じデータセットを保持するmongodインスタンスのグループのことです。レプリカセットには、複数のデータベアリング・ノードと、オプションで1つのアービター・ノードが含まれます。データ・ベアリング・ノードのうち、1つだけのメンバーがプライマリ・ノードとなり、他のノードはセカンダリ・ノードとなります。

プライマリ・ノードはすべての書き込み操作を受け取ります。レプリカセットには、{ w: "majority" } の書き込み懸念で書き込みを確認できるプライマリが1つだけ存在しますが、状況によっては別の mongod インスタンスが一時的に自分をプライマリだと思い込むこともあります。[1] プライマリは,データセットに対するすべての変更を操作ログ(oplog)に記録します。プライマリノードの操作については、「レプリカセット・プライマリ」を参照してください。

セカンダリーはプライマリのoplogを複製し、セカンダリーのデータセットがプライマリのデータセットを反映するように、自分のデータセットに演算を適用します。プライマリが利用できない場合は、資格のあるセカンダリが自分自身を新しいプライマリに選出する選挙を行います。セカンダリメンバーの詳細については、「レプリカセットのセカンダリメンバー」を参照してください。

状況によっては(プライマリとセカンダリがあるが、コストの関係でセカンダリをもうひとつ増やすことができないなど)、レプリカセットにアービターとしてmongodインスタンスを追加することができます。アービターは選挙に参加しますが、データを保持しません(つまり、データの冗長性を提供しません)。アービターの詳細については、「レプリカセットアービター」を参照してください。

アービターは常にアービターであるのに対し、プライマリーは退任してセカンダリーになり、セカンダリーは選挙中にプライマリーになる可能性があります。

Asynchronous Replication

セカンダリは、プライマリのオプログを複製し、非同期にデータセットに操作を適用します。セカンダリのデータセットにプライマリのデータセットを反映させることで、1つまたは複数のメンバーに障害が発生しても、レプリカセットは機能し続けることができます。

レプリケーションの仕組みの詳細については、「レプリカセットのオプローグ」と「レプリカセットのデータ同期」を参照してください。

Slow Operations

バージョン4.2から(4.0.6からも利用可能)、レプリカセットのセカンダリメンバーが、適用されるまでに遅い操作のしきい値よりも時間がかかるoplogエントリを記録するようになりました。これらの遅いoplogメッセージは、REPLコンポーネントの下にある診断ログに、セカンダリのためにopを適用したというテキストで記録されます。 took ms. これらの遅いoplogエントリーは、遅い操作のしきい値にのみ依存します。これらはログレベル(システムレベル、コンポーネントレベル)やプロファイリングレベル、遅い操作のサンプルレートには依存しません。プロファイラは遅いoplogのエントリをキャプチャしません。

Replication Lag and Flow Control

レプリケーション・ラグとは、プライマリで行われた書き込み操作をセカンダリにコピー(複製)するのにかかる時間のことです。多少の遅延時間は許容できるかもしれませんが、レプリケーションラグが大きくなると、プライマリのキャッシュが圧迫されるなど、重大な問題が発生します。

MongoDB 4.2 以降、管理者はプライマリが書き込みを行う速度を制限することができます。その目的は、コミットされた遅延の大部分を設定可能な最大値 flowControlTargetLagSeconds 以下に抑えることです。

デフォルトでは、フローコントロールが有効になっています。

NOTE

フロー制御を有効にするには、レプリカセット/シャードクラスタの featureCompatibilityVersion(FCV)が4.2で、read concern majorityが有効になっている必要があります。つまり、FCVが4.2でない場合や、リードコンシャスマジョリティが無効になっている場合は、フロー制御を有効にしても効果はありません。

フロー制御が有効な場合、ラグがflowControlTargetLagSecondsに近づくと、プライマリへの書き込みは、ロックをかけて書き込みを行う前にチケットを取得しなければならなくなります。1秒間に発行されるチケットの数を制限することで、フローコントロール機構は遅延を目標値以下に抑えようとします。

詳細については、「レプリケーションの遅延とフロー制御の確認」を参照してください。

Automatic Failover

プライマリが設定された electionTimeoutMillis 期間 (デフォルトでは 10 秒) を超えてセットの他のメンバーと通信しない場合、資格のあるセカンダリが自分を新しいプライマリとして指名するために選挙を要求します。クラスタは新しいプライマリの選出を完了し、通常の運用を再開しようとします。

選挙が正常に終了するまで、レプリカセットは書き込み操作を処理できません。プライマリがオフラインのときにセカンダリでクエリが実行されるように設定されている場合は、レプリカセットは読み取りクエリを処理し続けることができます。

クラスタが新しいプライマリを選択するまでの時間の中央値は、レプリカの設定がデフォルトの場合、通常は12秒を超えないようにしてください。これには、プライマリを利用できない状態にして、選挙を呼び出して完了するまでの時間が含まれます。この時間を調整するには、レプリケーション構成オプションのsettings.electionTimeoutMillisを変更します。ネットワークの遅延などの要因により、レプリカセットの選挙が完了するまでの時間が長くなることがあり、プライマリがいない状態でクラスタが動作する時間に影響します。これらの要因は、クラスタのアーキテクチャによって異なります。

electionTimeoutMillisレプリケーション設定オプションをデフォルトの10000(10秒)から下げると、プライマリの障害をより早く検出できるようになります。しかし、プライマリが正常であっても、一時的なネットワーク遅延などの要因により、クラスターがより頻繁に選挙を行う可能性があります。その結果、w:1の書き込み操作のロールバックが増加する可能性があります。

アプリケーションの接続ロジックには、自動フェイルオーバーとそれに続く選挙への耐性を持たせる必要があります。MongoDB 3.6 以降、MongoDB ドライバはプライマリが失われたことを検知して特定の書き込み操作を自動的に一度だけ再試行することができるようになり、自動フェイルオーバーと選択の処理が追加で組み込まれました。

  • MongoDB 4.2+ 互換のドライバは、デフォルトで再試行可能な書き込みを有効にします。
  • MongoDB 4.0 および 3.6 互換のドライバでは、 retryWrites=true を接続文字列に含めて明示的に再試行可能な書き込みを有効にする必要があります。

バージョン 4.4 以降、MongoDB はミラーリングされた読み込みを提供し、選挙で選ばれたセカンダリーメンバーのキャッシュを直近にアクセスされたデータで事前に暖めます。セカンダリーのキャッシュをあらかじめ温めておくことで、選挙後のパフォーマンスをより早く回復させることができます。

MongoDBのフェイルオーバープロセスについて詳しく知りたい方は、こちらをご覧ください。

Read Operations

Read Preference

デフォルトでは、クライアントはプライマリから読み取る[1]が、クライアントは読み取り優先順位を指定して、読み取り操作をセカンダリに送ることができる。

セカンダリへの非同期レプリケーションでは、セカンダリからの読み取りがプライマリ上のデータの状態を反映していないデータを返すことがあります。

読み取り操作を含むマルチドキュメント・トランザクションでは、プライマリへの読み取り優先度を使用する必要があります。あるトランザクション内のすべての操作は、同じメンバーにルーティングする必要があります。

レプリカ・セットからの読み取りについては、「読み取りの優先順位」を参照してください。

Data Visibility

読み手の関心に応じて、クライアントは書き込みが耐久性を持つ前に書き込みの結果を見ることができます。

  • 書き込みの懸念にかかわらず、「local」または「available」の読み取り懸念を使用する他のクライアントは、書き込み操作が発行クライアントに確認される前に、書き込み操作の結果を見ることができます。
  • ローカル」または「利用可能」な読み取り権限を持つクライアントは、レプリカセットのフェイルオーバー時に後からロールバックされる可能性のあるデータを読み取ることができます。

マルチドキュメントトランザクションでの操作では、トランザクションがコミットすると、そのトランザクションで行われたすべてのデータ変更が保存され、トランザクションの外からも見えるようになります。つまり、トランザクションでは、一部の変更をコミットし、他の変更をロールバックすることはありません。

トランザクションがコミットするまで、そのトランザクションで行われたデータ変更は、トランザクションの外では見えません。

しかし、トランザクションが複数のシャードに書き込む場合、外部のすべての読み取り操作が、コミットされたトランザクションの結果がシャード全体で見えるようになるのを待つ必要はありません。例えば、あるトランザクションがコミットされ、シャードAでは書き込み1が見えているが、シャードBでは書き込み2がまだ見えていない場合、リード・コンサーン「ローカル」の外部リードは、書き込み2を見ることなく、書き込み1の結果を読むことができます。

MongoDBのリードアイソレーション、一貫性、再帰性の詳細については、リードアイソレーション、一貫性、再帰性を参照してください。

Mirrored Reads

ミラーリングされた読み取りは、障害や計画的なメンテナンスの後にプライマリが選出される際の影響を軽減します。レプリカセットでフェイルオーバーが発生すると、新しいプライマリとして引き継いだセカンダリは、新しいクエリが入ってくるとキャッシュを更新します。キャッシュが暖まっている間、パフォーマンスに影響が出る可能性があります。

バージョン 4.4 以降、ミラーリングされた読み取りは、選択可能なセカンダリのレプリカセットメンバーのキャッシュを事前に暖めます。選択可能なセカンダリのキャッシュを温めるために、プライマリは受信したサポートされる操作の一部を選択可能なセカンダリにミラーリングします。

ミラーリングされた読み込みを受け取るセカンダリのレプリカセットのサイズは、 mirrorReads パラメータで設定できます。詳細は、「ミラーリング・リードのサポートの有効化/無効化」を参照してください。

NOTE

ミラーリングされた読み取りは、クライアントに対するプライマリの応答には影響しません。プライマリがセカンダリにミラーリングするリードは、「fire-and-forget」オペレーションです。プライマリは応答を待ちません。

Supported Operations

ミラーリードは以下の操作に対応しています。

Enable/Disable Support for Mirrored Reads

MongoDB 4.4 以降では、ミラーリングされた読み込みがデフォルトで有効になり、デフォルトのサンプリングレートとして 0.01 を使用します。ミラーリングされた読み込みを無効にするには、mirrorReads パラメータを { samplingRate: 0.0 }:

db.adminCommand( {
  setParameter: 1,
  mirrorReads: { samplingRate: 0.0 }
} )	

サンプリングレートが0.0より大きい場合,プライマリは,サポートされている読み取り値を,選択可能なセカンダリのサブセットにミラーリングする。サンプリングレートが0.01の場合、プライマリは受信したサポート付きリードの1%を各選択可能なセカンダリにミラーリングします。

1つのプライマリと2つの選択可能なセカンダリで構成されるレプリカセットを考えてみましょう。プライマリがミラーリング可能な1000回の操作を受け、サンプリング・レートが0.01の場合、プライマリは約10回の読み取りを選択可能なセカンダリに送ります。各選局可能なセカンダリは、10回の読み取りのうち、ほんの一部しか受信しません。ミラーリングされた各読み取りは、選択可能なセカンダリのうち、空ではない無作為に選ばれたものに送られます。

Change the Sampling Rate for Mirrored Reads

ミラーリードのサンプリングレートを変更するには、mirrorReadsパラメータに0.0から1.0の間の数値を設定します。

  • サンプリングレートが0.0の場合は、ミラーリングリードが無効になります。
  • サンプリングレートが0.0から1.0の間の数値である場合、プライマリは指定されたサンプルレートでサポートされている読み物のランダムなサンプルを選出されたセカンダリに転送します。
  • サンプリングレートが1.0の場合、プライマリはサポートされているすべてのリードを選択可能なセカンダリに転送します。

For details, see mirrorReads.

Mirrored Reads Metrics

MongoDB 4.4 以降、serverStatus コマンドと db.serverStatus() シェルメソッドは、操作でフィールドを指定すると mirroredReads メトリクスを返すようになりました。

db.serverStatus( { mirroredReads: 1 } )

Transactions

MongoDB 4.0 から、レプリカセットでmulti-document transactionsが使えるようになりました。

読み取り操作を含むマルチドキュメント・トランザクションでは、読み取り優先プライマリを使用する必要があります。特定のトランザクション内のすべての操作は、同じメンバーにルーティングする必要があります。

トランザクションがコミットするまで、そのトランザクションで行われたデータの変更は、トランザクションの外部からは見えません。

しかし、トランザクションが複数のシャードに書き込む場合、すべての外部の読み取り操作が、コミットされたトランザクションの結果がシャード間で見えるようになるのを待つ必要はありません。例えば、あるトランザクションがコミットされ、シャードAでは書き込み1が見えているが、シャードBでは書き込み2がまだ見えていない場合、リード・コンサーン「ローカル」の外部リードは、書き込み2を見ることなく、書き込み1の結果を読むことができます。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment