複製
MongoDB のレプリカセットは、同じデータセットを維持する mongod
プロセスのグループです。レプリカセットは冗長性と高可用性を提供し、すべての配置環境の基盤となります。このセクションでは、MongoDB のレプリケーションと、レプリカセットのコンポーネントおよびアーキテクチャについて紹介します。また、このセクションでは、レプリカセットに関連する一般的なタスクのチュートリアルも提供します。
MongoDB Atlas にホストされている配置に対して UI でレプリカセットを配置できます。
冗長性とデータ可用性
レプリケーションにより冗長性が確保でき、データの可用性が向上します。複数のデータベースサーバー上にデータのコピーを保持することで、レプリケーションは単一のデータベースサーバーが失われた場合でも、一定のフォールトトレランスを提供します。
場合によっては、クライアントが読み取り操作を別のサーバーに送信できるため、レプリケーションによって読み取りキャパシティーを増大することができます。異なるデータセンターにデータのコピーを保持することで、分散アプリケーションのためのデータローカリティと可用性を高めることができます。また、ディザスタリカバリ、レポート作成、バックアップなどの専用目的で追加のコピーを保持することもできます。
MongoDB でのレプリケーション
レプリカセットは、同じデータセットを保持する mongod
インスタンスのグループです。レプリカセットには、データを保持する複数のノードと、オプションとして 1 つのアービタ ノードが含まれます。データを保持するノードのうち、1 つのノードだけがプライマリノードと見なされ、他のノードはセカンダリノードと見なされます。
警告
各レプリカセット ノードの帰属先レプリカセットは 1 つのみにする必要があります。レプリカセット ノードは複数のレプリカセットに属することはできません。
プライマリ ノードはすべての書き込み操作を受け付けます。レプリカセットには、{ w: "majority" }
書き込み保証(write concern)で書き込みを確認できるプライマリが 1 つだけ存在します。ただし、状況によっては、別の mongod インスタンスが一時的に自分自身もプライマリであると認識する場合があります。[1] プライマリではデータセットに対するすべての変更を操作ログ(oplog)に記録します。プライマリ ノード操作の詳細については、「レプリカセット プライマリ」を参照してください。
セカンダリではプライマリの oplog を複製し、セカンダリのデータセットにプライマリのデータセットを反映するように操作をデータセットに適用します。プライマリが利用できない場合は、資格のあるセカンダリが選挙を行い、自分自身を新しいプライマリに選出します。セカンダリ ノードの詳細については、「レプリカセットのセカンダリ ノード」を参照してください。
状況によっては(プライマリとセカンダリがあるが、コストの制約により別のセカンダリを追加できない場合など)、レプリカセットに mongod
インスタンスをアービタとして追加することができます。アービタは選挙には参加しますが、データを保持していません(データの冗長性は提供されません)。アービタの詳細については、「レプリカセット アービタ」を参照してください。
アービタは 常にアービタであり続けますが、選挙中にプライマリが格下げしてセカンダリになったり、セカンダリがプライマリになったりすることもあります。
非同期レプリケーション
セカンダリはプライマリの oplog を複製し、非同期にデータセットに操作を適用します。セカンダリのデータセットにプライマリのデータセットを反映させることで、1 つ以上のノードに障害が発生しても、レプリカセットは機能し続けることができます。
レプリケーションの仕組みの詳細については、「レプリカセット Oplog」および「レプリカセット データ同期」を参照してください。
遅い操作
replica setのセカンダリ メンバーは、適用に低速操作しきい値よりも長い時間がかかるoplogをログに記録するようになりました。 これらの遅い oplog メッセージ:
ログは、テキスト
applied op: <oplog entry> took <num>ms
を含むREPL
コンポーネントの下にあります。ログレベルに依存しない(システムレベルでもコンポーネントレベルでも)
プロファイル レベルに依存しないでください。
slowOpSampleRate
の影響を受けます。
プロファイラーは遅い oplog エントリをキャプチャしません。
レプリケーションラグとフロー制御
レプリケーションラグは、プライマリでの操作と、その操作のoplogからセカンダリへの適用までの間の遅延です。 多少の遅延は許容できるかもしれませんが、レプリケーションラグが大きくなると、プライマリに対するキャッシュ負荷が増大するなど、重大な問題が発生します。
MongoDB 4.2 以降、majority
committed
の遅延を設定可能な最大値 flowControlTargetLagSeconds
以下に抑えることを目的として、プライマリが書き込み (write) を適用する速度を管理者が制限することができます。
デフォルトのフロー制御は、enabled
です。
注意
フロー制御を有効にするには、レプリカセットおよびシャーディングされたクラスターは、4.2
の FCV(featureCompatibilityVersion)を有し、かつ読み取り保証(read concern)がmajority enabled
である必要があります。つまり、FCV が 4.2
でない場合や、読み取り保証(read concern)の過半数が無効になっている場合、フロー制御を有効にしても効果はありません。
フロー制御が有効になっている場合、遅延が flowControlTargetLagSeconds
に近づくと、プライマリでの書き込み (write) は、書き込みを適用するためのロックを行う前にチケットを取得する必要があります。フロー制御メカニズムでは、1秒あたりに発行されるチケットの数を制限することで、遅延を目標値以下に保とうとします。
詳細については、「レプリケーションラグの確認」と「フロー制御」を参照してください。
自動フェイルオーバー
プライマリが、設定された electionTimeoutMillis
時間(デフォルトは 10 秒)を超えてセットの他のノードと通信しない場合、適格なセカンダリが選挙を呼びかけ、自身を新しいプライマリに指名します。クラスターは、新しいプライマリの選挙を完了し、通常の操作を再開しようとします。
レプリカセットは、選挙が正常に完了するまで、書き込み (write) 操作を処理できません。プライマリがオフラインのときにセカンダリ クエリを実行するように構成されている場合、レプリカセットは引き続き読み取りクエリを処理できます。
クラスターで新しいプライマリを選出するまでの時間の中央値は、デフォルトの replica
configuration settings
を前提とすると、通常 12 秒を超えることはありません。これには、プライマリを 利用不可 とマークし選挙を呼び出して完了するまでの時間も含まれます。この時間は、settings.electionTimeoutMillis
レプリケーション設定オプションを変更することで調整できます。ただし、ネットワーク レイテンシなどの要因により、レプリカセット選挙が完了するまでの時間が延長される可能性があり、それによりクラスターがプライマリなしで稼働する時間が影響を受けることがあります。これらの要因は、特定のクラスター アーキテクチャに依存します。
electionTimeoutMillis
のレプリケーション設定オプションをデフォルトの 10000
(10 秒)から下げると、プライマリ障害をより早く検出できるようになります。ただし、プライマリが正常であっても、一時的なネットワーク レイテンシなどの要因により、クラスターがより頻繁に選挙を呼び出すことがあります。これにより、w : 1 書き込み (write) 操作のロールバックが増加する可能性があります。
アプリケーション接続ロジックには、自動フェールオーバーとその後の選挙に対する許容範囲が含まれている必要があります。MongoDB ドライバーはプライマリの損失を検出し、自動的に 1 回、特定の書き込み操作を再試行することで、自動フェイルオーバーと選挙の組み込み処理を追加で行います。
互換性のあるドライバでは、デフォルトで再試行可能な書き込みが有効になります
MongoDB は、選出可能なセカンダリ ノードのキャッシュを最も最近アクセスされたデータを使用して事前にウォームアップするために、ミラーリングされた読み取りを提供します。セカンダリのキャッシュを事前にウォームアップすることで、選挙後のパフォーマンスをより迅速に復元できます。
MongoDB のフェイルオーバー プロセスの詳細については、以下を参照してください。
読み取り操作
読み込み設定 (read preference)
デフォルトでは、クライアントはプライマリ [1] から読み取りますが、クライアントは読み込み設定 (read preference) を指定して、読み取り操作をセカンダリに送信できます。
セカンダリへの非同期レプリケーションを実行した場合、セカンダリからの読み取りによって、プライマリのデータの状態を反映しないデータが返される可能性があります。
読み取り操作を含む分散トランザクションでは、読み込み設定(read preference) primary
を使用する必要があります。特定のトランザクション内のすべての操作は、同じノードにルーティングする必要があります。
レプリカセットからの読み取りについては、「読み込み設定 (read preference)」を参照してください。
データの可視性
読み取り保証(read concern)に応じて、クライアントは書込み(write)が永続的になる前にその書込みの結果を確認できます。
書き込み (write) の書込み保証 (write concern) に関係なく、
"local"
または"available"
の読み取り保証 (read concern) を使用する他のクライアントは、書き込み (write) 操作が発行クライアントに確認される前に、書き込み (write) 操作の結果を確認できます。"local"
または"available"
読み取り保証(read concern)を使用するクライアントにより、後でレプリカセットのフェイルオーバー中にロールバックされる可能性があるデータを読み取れます。
マルチドキュメントトランザクションの操作では、トランザクションがコミットされると、トランザクション内のすべてのデータ変更が保存され、トランザクションの外部に表示されます。つまり、トランザクションが他の変更をロールバックしながら、一部の変更をコミットすることはありません。
トランザクションがコミットされるまで、トランザクションで行われたデータ変更はトランザクションの外部には表示されません。
ただし、トランザクションが複数のシャードに書き込む場合、すべての外部読み取り操作が、コミットされたトランザクションの結果がシャード全体で表示されるまで待機する必要はありません。たとえば、トランザクションがコミットされ、書込み 1 がシャード A で表示されているものの、書込み 2 がシャード B にまだ表示されていない場合、読み取り保証(read concern) "local"
での外部読み取りは、書き込み 2 を見ることなく書き込み 1 の結果を読み取ることができます。
MongoDB の読み取り分離、整合性、直近性の詳細については、「読み取り分離、整合性、直近性について」を参照してください。
ミラーリングされた読み取り
ミラーリングされた読み取りにより、システム停止や計画的なメンテナンスの後のプライマリ選挙の影響を軽減できます。レプリカセットでフェイルオーバーが発生すると、新しいプライマリを引き継ぐセカンダリは、新しいクエリを受け取るとキャッシュを更新します。キャッシュがウォームアップしている間は、パフォーマンスに影響が出る可能性があります。
ミラーリングされた読み取りは、 electable
のセカンダリ レプリカセット ノードのキャッシュを事前にウォームアップします。 選択可能なセカンダリのキャッシュを事前にウォームアップするために、プライマリは、サポートされている 操作のサンプルを選択可能なセカンダリにミラーリングします。
ミラーリングされた読み取りを受信する electable
セカンダリ レプリカセット ノードのサブセットのサイズは、mirrorReads
パラメーターを使用して構成できます。詳細については、「ミラーリングされた読み取りのサポートの有効化と無効化」を参照してください。
注意
ミラーリングされた読み取りは、プライマリのクライアントへの応答には影響しません。プライマリからセカンダリにミラーリングする読み取りは、"fire-and-foreget" 操作で、プライマリは応答を待ちません。
サポートされている操作
ミラーリンされた読み取りは、次の操作をサポートします:
findAndModify
(具体的には、フィルターはミラーリングされた読み取りとして送信されます)update
(具体的には、フィルターはミラーリングされた読み取りとして送信されます)
ミラーリングされた読み取りのサポートの有効化と無効化
ミラーリングされた読み取りはデフォルトで有効になっており、 0.01
のデフォルトのsampling rate
が使用されます。 ミラーリングされた読み取りを無効にするには、 mirrorReads
パラメータを{
samplingRate: 0.0 }
に設定します。
db.adminCommand( { setParameter: 1, mirrorReads: { samplingRate: 0.0 } } )
サンプリング レートが0.0
を超えると、プライマリはサポートされている読み取りをelectable
セカンダリのサブセットにミラーリングします。 サンプリング レートが0.01
の場合、プライマリは、サポートされている読み取りの 1% を、選択可能なセカンダリの選択にミラーリングします。
たとえば、1 つのプライマリと 2 つの選出可能なセカンダリで構成されるレプリカセットを考えてみましょう。プライマリがミラーリング可能な 1000
操作を受信し、サンプリングレートが 0.01
の場合、プライマリはサポートされている約 10
回の読み取りを選出可能なセカンダリにミラーリングします。選出可能な各セカンダリは、10 回の読み取りのうちの一部のみを受け取ります。プライマリは、ミラーリングされた各読み取りを、ランダムに選択された空ではない選出可能なセカンダリに送信します。
ミラーリングされた読み取りのサンプリングレートを変更
ミラーリングされた読み取りのサンプリングレートを変更するには、mirrorReads
のパラメータを0.0
より大きく 1.0
より小さい数値に設定します。
サンプリング レートが
0.0
の場合、ミラーリングされた読み取りは無効になります。サンプリング レートが
0.0
から1.0
の間の数値の場合、プライマリは、指定されたサンプリング レートでサポートされている読み取りのランダムなサンプルを選択可能なセカンダリに転送します。サンプリング レートが
1.0
の場合、プライマリはすべてのサポートされている読み取りを選挙可能なセカンダリに転送します。
詳細については、mirrorReads
を参照してください。
ミラーリングされた読み取りのメトリクス
serverStatus
コマンドとdb.serverStatus()
shell メソッドでは、操作で フィールドを指定するとmirroredReads
メトリクスが返されます。
db.serverStatus( { mirroredReads: 1 } )
トランザクション
MongoDB 4.0 以降では、レプリカセットでマルチドキュメントトランザクションが利用できます。
読み取り操作を含む分散トランザクションでは、読み込み設定(read preference) primary
を使用する必要があります。特定のトランザクション内のすべての操作は、同じノードにルーティングする必要があります。
トランザクションがコミットされるまで、トランザクションで行われたデータ変更はトランザクションの外部には表示されません。
ただし、トランザクションが複数のシャードに書き込む場合、すべての外部読み取り操作が、コミットされたトランザクションの結果がシャード全体で表示されるまで待機する必要はありません。たとえば、トランザクションがコミットされ、書込み 1 がシャード A で表示されているものの、書込み 2 がシャード B にまだ表示されていない場合、読み取り保証(read concern) "local"
での外部読み取りは、書き込み 2 を見ることなく書き込み 1 の結果を読み取ることができます。
変更ストリーム
MongoDB 3.6 以降では、レプリカセットとシャーディングされたクラスターでストリーム変更を利用できます。ストリーム変更を使用すると、oplog を追尾する複雑さやリスクなく、アプリケーションがリアルタイムデータの変更にアクセスできます。アプリケーションはストリーム変更を使用して、1 つまたは複数のコレクションのすべてのデータ変更をサブスクライブできます。
追加機能
レプリカセットは、アプリケーションのニーズをサポートするためのさまざまなオプションを提供します。たとえば、複数のデータセンターのノードを持つレプリカセットを配置したり、一部のノードの members[n].priority
を調整して選挙の結果を制御したりできます。レプリカセットでは、レポート作成、障害復旧、またはバックアップ機能専用のノードもサポートします。
詳細については、「優先順位 0 のレプリカセット ノード」、 「非表示のレプリカセット ノード」、および「遅延レプリカセット ノード」を参照してください。
[1] | ( 1、2 )状況によっては、 replica set内の2つのノードが一時的に自分たちがプライマリであると認識することがありますが、最大でそのうちの1つが{ w:
"majority" } 書き込み懸念で書き込みを完了することができます。 { w: "majority" } 書き込みを完了できるノードは現在のプライマリであり、もう一方のノードは、通常はネットワークパーティションが原因で降格をまだ認識していない以前のプライマリです。これが発生すると、以前のプライマリに接続するクライアントは、読み取り設定primary を要求したにもかかわらず、古いデータを検出する可能性があり、以前のプライマリへの新しい書き込みは最終的にロールバックされます。 |