今回は「MongoDB の レプリケーション」についてその概要をまとめます。
タイトルには「レプリケーション」とありますがMongoDBでの実装にあたる「レプリカセット」の概要についてまとめています。
レプリケーション
「レプリケーション」はデータを複数のデータベースサーバーへコピーすることで冗長性と可用性を提供する仕組みです。 保存するデータセンターが異なれば災害対策にもなります。 また、同一データがコピーされているので読取が多いアプリケーションでは負荷分散も行えます。
MongoDBにおけるレプリケーション
MongoDB では同一データを保持するデータベースインスタンス群を「レプリカセット」と呼ばれるひとくくりのグループとして管理します。 MongoDB ではこのレプリカセットの仕組みで冗長性と可用性を提供します。
プライマリサーバーはすべての書き込み操作を受け取るサーバーで、データに対する変更を記録してログに残します。 セカンダリサーバーはプライマリサーバーの操作ログをコピーして適用することでプライマリサーバーと同じデータの状態を作ります。 もし、プライマリサーバーが不通となった場合は適切なセカンダリサーバーがプライマリサーバーに選任されてサービスを継続します。
レプリカセットメンバー
MongoDB の レプリカセット に含まれるメンバー(サーバー)の種類は以下にあげる3種類があります。
- プライマリ
- セカンダリ
- アービター
それぞれについて以下で詳しく紹介します。
プライマリ
レプリカセット中に1台だけ存在する書き込み可能なサーバーです。 プライマリサーバーに書き込んだ操作情報はログ oplog として残り、この操作ログがセカンダリサーバーへ伝達、コピーされます。
プライマリサーバーが何かしらの理由でお亡くなりになった場合、残ったセカンダリサーバーの中から次のプライマリサーバーが投票で選任されます。
セカンダリ
プライマリサーバーの操作ログをもとにデータ更新を行う読み取り専用のサーバーです。 セカンダリサーバーを複数台用意することで大量の読み取り操作に耐えられるようにします。
クライアントからのデータ読み取りは、基本的にセカンダリサーバー優先で読みに行くようにし、即時性が求められるデータのみプライマリサーバー優先で読みに行くようにします。
セカンダリサーバーの主な設定には「優先度(Priority)」「隠し(Hidden)」「遅延(Delayed)」の3つがあります。
-
優先度(Priority)
Priority: 0
を指定するとプライマリサーバーに昇格しません。 優先度が0より大きな値が設定されているサーバーからプライマリサーバーが選任されます。 また、優先度に高い値が設定されているサーバーが優先的にプライマリサーバーとして選任されます。 -
隠し(Hidden)
プライマリサーバーから操作ログをコピーしてデータ最新化は行いますが、クライアントアプリケーションからは見えない設定です。 クライアントアプリケーションから見えないので、他のサーバーに比べて負荷は低くなります。 隠し設定にしたメンバーはデータ分析やバックアップなど通常業務と異なる専用端末として利用します。
-
遅延(Delayed)
プライマリサーバーから操作ログをコピーしてデータ反映は行いますが、プライマリサーバーよりも指定時間分だけ遅延させて反映します。 プライマリサーバーよりも遅延させて反映させることで、何かしら操作ミスを起こしてしまった時のリカバリに利用できるようにします。
アービター
レプリカセットで投票権のあるサーバーを奇数台にするために追加する調整用のサーバーです。
アービターサーバー自体はデータを持たず、プライマリサーバーが亡くなった場合に行われる新しいプライマリサーバーの選任で投票を行うことが主な役割です。
自身がプライマリサーバーになることはないので Priority: 0
を指定しておきます。
レプリカセットの構成
レプリカセットには最大50台までのメンバーを含めることができ、そのうち最大7台までが投票権を持ちます。 投票権を持つサーバー台数は奇数になるよう設計します。 足りない場合はアービターを追加して調整します。
最小のレプリカセットは3台構成で、以下のような構成が想定されます。
- プライマリとセカンダリ2台
- プライマリとセカンダリ、アービター
地理的に離れたデータセンターにメンバーを配置することでより高い可用性を実現することができます。
プライマリ と セカンダリ2台
このパターンの場合、セカンダリサーバー2台ともがプライマリサーバーになれるので、より可用性が高い構成となります。
通常時は2台のセカンダリサーバーに完全なコピーが作られます。 プライマリサーバーが不通となった場合、残っている2台のセカンダリサーバーが投票を行い、どちらかがプライマリサーバーに昇格します。
プライマリ と セカンダリ、アービター
いわゆるサーバー2台構成です。 実態として動いているのはプライマリサーバーとセカンダリサーバーの2台のみで、アービターサーバーはフェールオーバー時の投票に参加するくらいです(とはいえ、セカンダリにアービター相乗りさせるのは推奨されないので、管理用サーバーなど物理的に異なる低スペックサーバーにしておきます)。
このパターンの場合、アービターサーバーにデータコピーされないので、完全なコピーはセカンダリサーバーのみとなります。 プライマリサーバーが不通となった場合、プライマリサーバーの投票は行われますが必然的に残っているセカンダリサーバーがプライマリサーバーに昇格します。
自動フェールオーバー
レプリカセットは自動フェールオーバーによって高可用性を実現します。 具体的には、プライマリサーバーが応答しなくなった際、セカンダリサーバーから次のプライマリサーバーを選任し、選任されたセカンダリサーバーがプライマリサーバーに昇格することで実現します。
各メンバーは2秒間隔でハートビート(ping)を実行します。 10秒間応答が得られなかった場合、該当サーバーを不良サーバーとしてマークします。 プライマリサーバーが不良サーバーと設定されると残ったセカンダリサーバーから次のプライマリサーバーの選任始まります。
サーバーが投票を行う際、より高い優先度(Priority)が設定されたサーバーが優先的にプライマリサーバーに選任されます。 優先度(Priority)が低いサーバーが選任されている状態で、より高い優先度(Priority)のサーバーが有効になった場合、再び優先度(Priority)が高いサーバーがプライマリサーバーとなるよう投票が行われます。
投票を行わないメンバーは優先度(Priority)を0に設定しておきます。 1つのレプリカセットで投票権は7つまでなので、それ以上のセカンダリサーバーを用記す場合は優先度(Priority)を0として投票権(votes)も0で設定したサーバーにします。
データの読み書き
データの読み込みも書き込みも MongoClient の生成時にオプションで指定できます。 書き込みに関しては w, j, wtimeout の3種類、 読み込みに関しては readPreference, readConcern.level の2種類があります。
var {MongoClient, ReadPreference}= require("mongodb"); var URL = "mongodb://localhost:27017/test"; MongoClient.connect(URL, { // 書き込み設定 w: "majority", j: true, wtimeout: 5000, // 読み込み設定 readPreference: ReadPreference.SECONDARY_PREFERRED readConcern: { level: "local" } }, (client) => { client.close(); });
データ書き込み
書き込みは Write Concern
設定でレプリカセットに含まれるサーバーの何台目まで書き込み処理を伝搬するか指定します。
w
設定値 | 説明 |
---|---|
<number> | 指定した台数まで書き込まれることを保証します。 |
"majority" | 投票権のあるサーバーの過半数に書き込まれることを保証します。 |
j
設定値 | 説明 |
---|---|
true | ディスクへの書き込みまで行います。 |
false | デフォルト。メモリ上への書き込みのみを保証します。 |
wtimeout
設定値 | 説明 |
---|---|
<number> | 書き込みをタイムアウトにする時間(ミリ秒)を指定します。 設定する場合は1より大きな値を指定します。 0を指定した場合、タイムアウト処理を行いません。 |
データ読み込み
読み込みは Read Preference 設定でどのサーバーから優先的にデータ読み込みするかを設定することができます。
readPreference
設定値 | 説明 |
---|---|
primary | デフォルトモード。プライマリサーバーから取得します。 |
primaryPreferred | ほとんどの場合はプライマリサーバーから取得しますが、プライマリサーバーにアクセスできない場合はセカンダリサーバーから取得します。 |
secondary | セカンダリサーバーから取得します。 |
secondaryPreferred | ほとんどの場合はセカンダリサーバーから取得しますが、セカンダリサーバーにアクセスできない場合はプライマリサーバーから取得します。 |
nearest | レプリカセットの種類に関わらず、レイテンシーが最小のサーバーから取得します。 |
readConcern.level
どのようなデータを取得してくるかを指定します。
設定値 | 説明 |
---|---|
"local" | デフォルトでプライマリを読みに行きます。 インスタンスの最も新しいデータを取得してきます。 レプリカセットのほとんどに書き込まれたデータかどうかまでは保証しません。 |
"available" | デフォルトでセカンダリを読みに行きます。 インスタンスの最も新しいデータを取得してきます。 レプリカセットのほとんどに書き込まれたデータかどうかまでは保証しません。 |
"majority" | ほとんどのメンバーに書き込まれたデータの最も新しいデータを取得します。 |
"linearizable" | すべての書き込みが終わった後のロールバックされないデータを取得します。 |
今回は「MongoDB の レプリケーション」についてまとめました。 ポイントは以下の通りです。
- 書き込みできるのはプライマリサーバーのみ。
- プライマリサーバーが不通となった場合、残ったセカンダリサーバーがプライマリサーバーに昇格。
参考になったでしょうか? 本記事がお役に立っていると嬉しいです!!
参考記事
- MongoDB - Replication
- MongoDB - Replica Set Members
- MongoDB - Replica Set Primary
- MongoDB - Priority 0 Replica Set Members
- MongoDB - Hidden Replica Set Members
- MongoDB - Delayed Replica Set Members
- MongoDB - Replica Set Arbiter
- gihyo.jp - 第4回 MongoDBのレプリケーションを構築してみよう
- Qiita - 俺でもわかるシリーズ: MongoDBのレプリケーション
- MongoDB - Write Concern
- MongoDB - Read Preference
- MongoDB - Read Concern
最後に… このブログに興味を持っていただけた方は、 ぜひ 「Facebookページ に いいね!」または 「Twitter の フォロー」 お願いします!!