MongoDB: レプリケーション:高可用性アーキテクチャ
最終更新:2026-08-26
レプリカセットはMongoDB高可用性の要—習得すれば99.99%の可用性を持つ本番クラスターを構築できます。
1. 学習内容
- レプリカセットの概念(Primary / Secondary / Arbiter)
- 選挙メカニズム(Raftベース)
- データ同期(初期同期 / oplog追跡)
- 読み書き分離(readPreference)
- Dockerでの3ノードレプリカセット構築
- フェイルオーバーと復旧
2. レプリカセットアーキテクチャ
概念概要: レプリカセットはMongoDB高可用性アーキテクチャの基盤です。複数のmongodプロセスで構成—1つのPrimaryノード + N個のSecondaryノード + オプションのArbiterノード。Primaryノードは全ての書き込み操作を受け付け、oplog経由でSecondaryノードに非同期で複製し、データ冗長性と自動フェイルオーバーを実現します。
動作原理: Primaryは全ての書き込み操作をoplog(固定サイズのcappedコレクション)に記録し、Secondaryはoplogを追跡(tail)して書き込み操作を継続的に取得・再生し、Primaryとのデータ整合性を維持します。Primaryが障害発生すると、残りのノードが選挙プロトコル(Raftベース)で新しいPrimaryを選出し、アプリケーションは自動的に再接続し、99.99%の可用性を実現します。
Raftプロトコルと選挙メカニズム: MongoDBの選挙プロセスはRaftプロトコルの派生版に基づいており、コアルールは「過半数ルール」です—過半数以上のノードから票を獲得した候補だけがPrimaryになれます。これにより、任意の時点で最大1つのPrimaryが存在すること(スプリットブレイン防止)と、新しいPrimaryが最も完全なデータを持つことが保証されます。
graph TB
App[アプリケーション] --> P[Primary<br/>マスターノード<br/>全書き込みを受け付け]
P -.oplog複製.-> S1[Secondary 1<br/>スレーブノード<br/>読み取り可能+バックアップ]
P -.oplog複製.-> S2[Secondary 2<br/>スレーブノード<br/>読み取り可能+バックアップ]
A[Arbiter<br/>調停ノード<br/>投票のみ]
subgraph "データフロー"
W[書き込み] --> P
P -->|oplog| S1
P -->|oplog| S2
end
subgraph "選挙"
P -->|ハートビート| S1
P -->|ハートビート| S2
P -->|ハートビート| A
end
style P fill:#d4edda
style S1 fill:#cce5ff
style S2 fill:#cce5ff
style A fill:#fff3cd
ノード役割の比較:
| ノード | 責務 | データ保存 | 読み取り可能 | 選挙参加 | 優先度 |
|---|---|---|---|---|---|
| Primary | 全書き込み操作を受け付け | ✅ | ✅ | ✅ | デフォルト1(増加可能) |
| Secondary | Primaryデータを複製 | ✅ | ✅(設定必要) | ✅ | デフォルト1 |
| Arbiter | 選挙投票のみ参加 | ❌ | ❌ | ✅ | 0(選出不可) |
レプリカセット vs 単一ノード:
| 項目 | 単一ノード | レプリカセット |
|---|---|---|
| 可用性 | 単一障害点 | 99.99%(自動フェイルオーバー) |
| データ安全性 | ディスク障害=データ消失 | マルチコピー冗長性 |
| 読み取り拡張 | なし | Secondary読み取り負荷分散 |
| トランザクション対応 | ❌ | ✅(レプリカセット必要) |
| 運用複雑さ | 低い | 中程度 |
3. レプリカセットの起動
概念説明: レプリカセットの起動は2ステップ:1) --replSetパラメータでmongodプロセスを起動、2) mongoshでrs.initiate()を実行してレプリカセット設定を初期化。初期化時に全メンバーのアドレスを指定し、MongoDBが自動的にPrimaryを選出します。
動作原理: rs.initiate()はレプリカセット設定を各ノードのローカルデータベースに書き込み、選挙プロトコルをトリガーします。最初に初期化されたノードが通常Primaryになり、他のノードは自動的に設定を同期しoplog追跡を開始します。
# === 最初のノードを起動(レプリカセットモード)===
mongod --replSet rs0 --port 27017 --dbpath /data/db1 --bind_ip localhost
# === mongoshで初期化 ===
mongosh
> rs.initiate({
_id: 'rs0',
members: [
{ _id: 0, host: 'localhost:27017' },
{ _id: 1, host: 'localhost:27018' },
{ _id: 2, host: 'localhost:27019' }
]
});
初期化設定パラメータ:
| パラメータ | 説明 | 例 |
|---|---|---|
_id |
レプリカセット名、--replSetと一致させる |
'rs0' |
members |
メンバー一覧 | [{_id: 0, host: '...'}] |
members._id |
メンバーID(一意) | 0, 1, 2 |
members.host |
メンバーアドレス | 'localhost:27017' |
members.priority |
選挙優先度(0 = 選出不可) | デフォルト1 |
settings.electionTimeoutMillis |
ハートビートタイムアウト | デフォルト10000ms |
4. ノードの追加・削除
概念説明: レプリカセットはオンラインでのノード追加・削除をサポートし、サービス停止は不要です。ノード追加後、新ノードは自動的にPrimaryから初期同期(フル同期)を実行し、その後oplog追跡(増分同期)に切り替わります。
データ同期プロセス:
sequenceDiagram
participant New as 新規ノード
participant P as Primary
participant Oplog as oplog
New->>P: レプリカセットへの参加リクエスト
P-->>New: 確認 + 現在の設定
Note over New,P: フェーズ1: 初期同期(フル同期)
New->>P: 全データをリクエスト
P-->>New: 全コレクションデータ + インデックス
Note over New,P: フェーズ2: Oplog追跡(増分同期)
loop 継続
New->>Oplog: 最新oplogエントリを取得
Oplog-->>New: 増分操作
New->>New: oplog操作を再生
end
Note over New: 同期完了後、選挙に参加可能
| 操作 | コマンド | 説明 |
|---|---|---|
| データノード追加 | rs.add('host:port') |
自動初期同期 |
| 調停ノード追加 | rs.addArb('host:port') |
投票のみ、データ保存なし |
| ノード削除 | rs.remove('host:port') |
自動ノード降格 |
| ステータス確認 | rs.status() |
全ノードステータス + 健康 |
| 設定確認 | rs.conf() |
レプリカセット設定詳細 |
// === 新規ノード追加 ===
rs.add('localhost:27020');
// === Arbiter追加(データ保存なし)===
rs.addArb('localhost:27021');
// === ノード削除 ===
rs.remove('localhost:27020');
// === レプリカセットステータス確認 ===
rs.status();
ポイント解説:
- 初期同期中、新ノードは選挙や読み取りサービスに参加しません。同期完了後、自動的にSecondaryノードになります。
- 大規模データセットの初期同期は時間がかかる(100GBで数時間の可能性)、オフピーク時間帯の追加を推奨。
- Arbiterはデータを保存しません。奇数ノードでの投票参加を保証するためだけに使用し、優先度は0です。
5. 選挙メカニズム(Raftベース)
概念説明: 選挙メカニズムはレプリカセット高可用性の中核です—Primary障害時、Secondaryが自動的に選挙を開始して新しいPrimaryを選出します。MongoDBの選挙はRaftプロトコルの派生版に基づき、コア保証は「任意の時点で最大1つのPrimary」(スプリットブレイン防止)と「新しいPrimaryが最も完全なデータを持つ」ことです。
Raft選挙プロセス:
- 障害検出: SecondaryがelectionTimeout(デフォルト10秒)以内にPrimaryからハートビートを受信しない
- 選挙開始: 利用可能なSecondaryのうち優先度が最も高いものが候補になり、termをインクリメント
- 投票リクエスト: 候補は全ノードに投票リクエストを送信
- 投票ルール: 各ノードは1つのtermで1票のみ投票、最も最新のデータを持つ候補に投票
- 過半数選出: 過半数以上の票(> N/2)を獲得した候補が新しいPrimaryになる
- アプリ再接続: ドライバは自動的に新しいPrimaryを検出し、透過的に切り替え
sequenceDiagram
participant S1 as Secondary 1<br/>(候補)
participant S2 as Secondary 2
participant A as Arbiter
Note over S1: Primaryハートビートタイムアウト10秒<br/>選挙を呼び出し
S1->>S1: termをインクリメント = 2<br/>自分に投票
S1->>S2: RequestVote(term=2, lastOplogTime)
S1->>A: RequestVote(term=2, lastOplogTime)
S2->>S1: GrantVote ✅<br/>(データが十分に最新)
A->>S1: GrantVote ✅
Note over S1: 過半数の票を獲得(2/3)<br/>新しいPrimaryになる
S1->>S2: Heartbeat(term=2, role=PRIMARY)
S1->>A: Heartbeat(term=2, role=PRIMARY)
Note over S1,S2: 選挙終了、アプリは自動再接続
主要な選挙パラメータ:
| 選挙ルール | 説明 | デフォルト値 |
|---|---|---|
| トリガー | PrimaryがelectionTimeout以上到達不能 | 10秒 |
| 候補 | 全Secondary + Arbiter | — |
| 投票 | 過半数以上の票(> 半数)を獲得でPrimaryに | — |
| 優先度 | 高い優先度のノードが優先選出 | 1 |
| データ完全性 | 投票者は最新のoplogを持つ候補にのみ投票 | — |
| 選挙クールダウン | 頻繁な選挙を防止 | 30秒 |
graph LR
A[Primary障害] --> B[Secondary検出]
B --> C{過半数の票を獲得?}
C -->|はい| D[Primaryに昇格]
C -->|いいえ| E[待機]
D --> F[アプリ再接続]
style D fill:#d4edda
| 選挙ルール | 説明 |
|---|---|
| トリガー | PrimaryがelectionTimeout以上到達不能 |
| 候補 | 全Secondary + Arbiter |
| 投票 | 過半数以上の票(> 半数)を獲得でPrimaryに |
| 優先度 | 高い優先度のノードが優先選出 |
なぜ奇数ノードが必要か: 3ノードシステムは1つの障害を許容(2/3過半数投票)、4ノードシステムも1つの障害しか許容(3/4過半数投票)、5ノードシステムは2つの障害を許容(3/5過半数投票)。偶数ノードは耐障害性を増やさずコストが増えるため、奇数ノードを推奨。
▶ サンプル 1:選挙優先度設定
// TechCorp:より強力なサーバーを優先的にPrimaryに
rs.reconfig({
_id: 'rs0',
members: [
{ _id: 0, host: 'mongo1:27017', priority: 3 }, // 最強サーバー、圧倒的に選出
{ _id: 1, host: 'mongo2:27017', priority: 2 }, // 第2選択
{ _id: 2, host: 'mongo3:27017', priority: 1 }, // 最も低い優先度
{ _id: 3, host: 'mongo4:27017', priority: 0 } // 選出不可(コールドスタンバイ)
]
});
出力:
TEXT 📖 参照専用{ "ok" : 1 }
6. 読み書き分離
概念説明: レプリカセットは本質的に読み書き分離をサポート—書き込み操作はPrimaryにルーティングされ、読み取り操作はSecondaryに分散可能です。readPreferenceで読み取りルーティングポリシーを設定し、読み取り集中型シナリオでPrimaryの負荷を大幅に削減できます。
動作原理: Mongoose/MongoドライバはreadPreferenceパラメータを使用して、読み取り操作をどのノードに送信するかを決定します。primaryは強整合性を保証し、secondaryはPrimaryノードの負荷を削減しますが、レプリケーション遅延が発生します。
readPreference詳細:
| モード | 動作 | 整合性 | 遅延 | 使用シーン |
|---|---|---|---|---|
primary |
プライマリノードのみ読み取り | 最高 | 最低 | トランザクション、重要データ |
primaryPreferred |
プライマリ優先、不可ならセカンダリ | 強い | 低い | 一般的なシーン |
secondary |
セカンダリノードのみ読み取り | 弱い | 高い | レポート/分析 |
secondaryPreferred |
セカンダリ優先、不可ならプライマリ | より弱い | より低い | 読み取り多・書き込み少 |
nearest |
ネットワーク遅延最小 | 不定 | 最低 | 地理分散 |
整合性 vs パフォーマンスのトレードオフ:
graph LR
A[primary<br/>強整合性<br/>高遅延] --> B[primaryPreferred<br/>強整合性]
B --> C[secondaryPreferred<br/>弱整合性]
C --> D[secondary<br/>弱整合性<br/>低遅延]
D --> E[nearest<br/>不定<br/>最低遅延]
style A fill:#d4edda
style D fill:#fff3cd
// === デフォルト:全読み書きがPrimaryで実行 ===
const user = await User.findById(userId);
// === セカンダリから読み取り(Primary負荷軽減)===
const products = await Product.find().read('secondary');
// === 読み取り設定オプション ===
await Product.find().read('primary'); // マスターノードのみ
await Product.find().read('primaryPreferred'); // プライマリ優先
await Product.find().read('secondary'); // スレーブノードのみ
await Product.find().read('secondaryPreferred'); // セカンダリ優先
await Product.find().read('nearest'); // 最も近いノード
ポイント解説:
- セカンダリからの読み取りはレプリケーション遅延が発生する可能性(通常< 1秒、ネットワーク問題時はより長く)。
secondaryモードでは、全Secondaryノードが利用不可の場合、クエリはエラーを返します。- レポートや検索インデックス構築など整合性がそれほど重要でないシナリオでは、
secondaryまたはsecondaryPreferredを推奨。
7. Dockerでの3ノード構築
概念説明: Docker Composeはローカルでレプリカセットを開発・テストする最も便利な方法です。3ノード構成(1 Primary + 2 Secondary)は推奨される最小の本番構成で、高可用性と自動フェイルオーバーを提供します。
デプロイアーキテクチャ:
graph TB
subgraph "Docker Compose"
M1[mongo1:27017<br/>Primary/Secondary]
M2[mongo2:27017<br/>Primary/Secondary]
M3[mongo3:27017<br/>Primary/Secondary]
end
App[アプリケーション] --> M1
App --> M2
App --> M3
M1 <--> M2
M2 <--> M3
M1 <--> M3
style M1 fill:#d4edda
style M2 fill:#cce5ff
style M3 fill:#cce5ff
# docker-compose.yml
version: '3.8'
services:
mongo1:
image: mongo:7.0
command: mongod --replSet rs0 --port 27017
ports:
- "27017:27017"
mongo2:
image: mongo:7.0
command: mongod --replSet rs0 --port 27017
ports:
- "27018:27017"
mongo3:
image: mongo:7.0
command: mongod --replSet rs0 --port 27017
ports:
- "27019:27017"
// === レプリカセット初期化 ===
rs.initiate({
_id: 'rs0',
members: [
{ _id: 0, host: 'mongo1:27017' },
{ _id: 1, host: 'mongo2:27017' },
{ _id: 2, host: 'mongo3:27017' }
]
});
デプロイステップ:
| ステップ | コマンド | 説明 |
|---|---|---|
| 1 | docker-compose up -d |
3コンテナを起動 |
| 2 | mongosh --port 27017 |
最初のノードに接続 |
| 3 | rs.initiate({...}) |
レプリカセット初期化 |
| 4 | rs.status() |
ステータス確認 |
| 5 | rs.conf() |
設定確認 |
8. フェイルオーバー
概念説明: フェイルオーバーはレプリカセットの最も重要な機能です—Primaryノード障害時、残りのノードが自動的に新しいPrimaryを選出し、アプリケーションは透過的に再接続します。全プロセスは通常10–30秒で完了、この間書き込みは不可ですが、読み取りはSecondaryノードに縮退可能です。
フェイルオーバープロセス:
sequenceDiagram
participant App as アプリケーション
participant P as Primary (mongo1)
participant S1 as Secondary (mongo2)
participant S2 as Secondary (mongo3)
Note over P: mongo1障害
P-xApp: ハートビート切断
P-xS1: ハートビート切断
P-xS2: ハートビート切断
Note over S1,S2: 10秒間Primaryハートビート未受信
S1->>S2: 選挙を呼び出し
S2->>S1: 賛成票
S1->>S1: 過半数の票獲得(2/3)
Note over S1: mongo2が新しいPrimaryに
App->>S1: 自動再接続 → 書き込み復旧
App->>S2: 読み取り継続(secondaryPreferred)
Note over App,S1: 合計ダウンタイム: 10-30秒
| 障害シナリオ | 影響 | 復旧時間 |
|---|---|---|
| Primary停止 | 書き込み中断10–30秒 | 自動選挙復旧 |
| Secondary停止 | 影響なし | 再起動後自動同期 |
| 過半数ノード停止 | レプリカセット読み取り専用 | 過半数ノード復旧必要 |
| ネットワーク分断 | 少数側は書き込み不可 | ネットワーク復旧後自動統合 |
# === Primary停止をシミュレート ===
# mongo1コンテナをkill
docker stop mongo1
# === 自動選挙(30秒で完了)===
# mongo2またはmongo3が自動的にPrimaryに昇格
# === アプリ自動再接続(mongoose設定)===
mongoose.connect('mongodb://mongo1,mongo2,mongo3/shopdb?replicaSet=rs0');
アプリ層のトラブルシューティング:
| 設定 | 説明 | 推奨値 |
|---|---|---|
| 接続文字列 | 全ノードをリスト | mongodb://m1,m2,m3/db?replicaSet=rs0 |
| リトライ書き込み | ネットワークエラーを自動リトライ | retryWrites=true |
| 読み取り設定 | 障害時の読み取り縮退 | secondaryPreferred |
| 接続タイムアウト | 接続タイムアウト時間 | connectTimeoutMS=5000 |
| サーバー選択タイムアウト | ノード選択タイムアウト | serverSelectionTimeoutMS=30000 |
9. レプリカセットのベストプラクティス
概念概要: レプリカセットのベストプラクティスは、ノード数、セキュリティ設定、監視アラートなどを網羅します。これらの実践に従うことで、本番環境での一般的なレプリカセット障害を防止できます。
主要な実践:
| 実践 | 説明 | 理由 |
|---|---|---|
| 3ノード構成 | 1 Primary + 2 Secondary | 最小耐障害構成、1ノード障害を許容 |
| 奇数ノード | 選挙には過半数票が必要: 3/5/7 | 偶数ノードは耐障害性を増やさない |
| writeConcern: majority | 過半数ノードで書き込み確認 | データ消失なし(Primary障害でも) |
| readPreference primaryPreferred | デフォルトでプライマリ読み取り | 整合性保証、プライマリ不可ならセカンダリ |
| oplogウィンドウ監視 | oplogロールオーバーはデータ消失の原因 | ウィンドウ > 24時間を維持 |
| 適切な優先度設定 | 強力サーバーは高い優先度 | 障害復旧後、強力サーバーが再選出 |
| Arbiterは慎重に使用 | コスト重視時のみ使用 | Arbiterはデータ保存せず、復旧不可 |
writeConcernの比較:
| writeConcern | データ安全性 | 書き込み遅延 | 使用シーン |
|---|---|---|---|
w: 1 |
Primary確認のみ | 最速 | ログ、非重要データ |
w: majority |
過半数ノード確認 | 中程度 | 一般ビジネスデータ |
w: majority, j: true |
過半数確認 + journalディスク書き込み | 最も遅い | 金融、重要データ |
監視チェックリスト:
| 監視項目 | コマンド | 健全値 | アラート閾値 |
|---|---|---|---|
| レプリカセットステータス | rs.status() |
1 PRIMARY + N SECONDARY | PRIMARYなし |
| レプリケーション遅延 | rs.status().members[n].optimeDate |
< 1秒 | > 10秒 |
| oplogウィンドウ | rs.printReplicationInfo() |
> 72時間 | < 24時間 |
| 接続数 | db.serverStatus().connections |
< 1000 | > 8000 |
| 選挙回数 | rs.status().electionMetrics |
少ない | 頻繁な選挙 |
▶ サンプル:Dockerで3ノードレプリカセット構築 + フェイルオーバーテスト
# === 1. docker-compose.yml ===
# version: '3.8'
# services:
# mongo1:
# image: mongo:7.0
# command: mongod --replSet rs0 --bind_ip_all --port 27017
# ports: ["27017:27017"]
# networks: [mongo-net]
#
# mongo2:
# image: mongo:7.0
# command: mongod --replSet rs0 --bind_ip_all --port 27017
# ports: ["27018:27017"]
# networks: [mongo-net]
#
# mongo3:
# image: mongo:7.0
# command: mongod --replSet rs0 --bind_ip_all --port 27017
# ports: ["27019:27017"]
# networks: [mongo-net]
#
# networks:
# mongo-net:
# driver: bridge
# 3ノード起動
docker-compose up -d
# === 2. レプリカセット初期化 ===
mongosh --port 27017 --eval '
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "localhost:27017" },
{ _id: 1, host: "localhost:27018" },
{ _id: 2, host: "localhost:27019" }
]
});
'
# === 3. レプリカセットステータス確認 ===
mongosh --port 27017 --eval 'rs.status();'
# 出力:
# {
# set: 'rs0',
# members: [
# { name: 'localhost:27017', stateStr: 'PRIMARY' },
# { name: 'localhost:27018', stateStr: 'SECONDARY' },
# { name: 'localhost:27019', stateStr: 'SECONDARY' }
# ]
# }
# === 4. テストデータ書き込み(自動的にSecondaryに複製)===
mongosh --port 27017 --eval '
db.products.insertOne({ sku: "PHONE-001", title: "Smartphone X", price: 599 });
'
# === 5. データ複製を確認 ===
mongosh --port 27018 --eval '
db.setSecondaryOk(); // Secondary読み取り許可
db.products.findOne({ sku: "PHONE-001" });
'
# 同じドキュメントを返す、複製成功を証明
# === 6. フェイルオーバーテスト ===
# Primaryを停止
docker stop mongo1
# mongo2で確認
mongosh --port 27018 --eval 'rs.status();'
# 出力:mongo2が自動的にPRIMARYに昇格(30秒で完了)
# === 7. アプリ自動再接続(mongoose)===
// mongoose接続文字列は自動的に全ノードを発見
const mongoose = require('mongoose');
await mongoose.connect(
'mongodb://localhost:27017,localhost:27018,localhost:27019/shopdb?replicaSet=rs0'
);
// Primary障害でも、アプリは自動的に新しいPrimaryに接続
const products = await Product.find(); // 自動リトライ、エラーなし
// === 8. 読み書き分離設定 ===
// 書き込み操作はPrimaryで完了
await Product.create({ sku: 'PHONE-002', title: 'Phone 2' });
// 読み取り操作はSecondaryで可能(Primary負荷軽減)
const products = await Product.find().read('secondaryPreferred');
// === 9. 障害ノード復旧 ===
docker start mongo1
# mongo1は自動的にSecondaryとしてレプリカセットに参加、Primaryからデータ同期開始
出力:
TEXT 📖 参照専用3ノードレプリカセットが高可用性を提供;Primary障害時、30秒以内に自動フェイルオーバー、アプリへの影響なし。
▶ サンプル 3:読み取り設定とフェイルオーバーを備えたNode.jsアプリケーション(難易度 ⭐⭐)
// シーン:ShopHubアプリケーションがレプリカセットに接続、自動フェイルオーバー付き
const mongoose = require('mongoose');
// レプリカセットメンバーを含む接続文字列
const uri = 'mongodb://mongo1:27017,mongo2:27017,mongo3:27017/shophub?' +
'replicaSet=rs0&' +
'readPreference=primaryPreferred&' +
'w=majority&' +
'maxPoolSize=50';
// リトライロジック付きで接続
async function connectWithRetry() {
try {
await mongoose.connect(uri, {
serverSelectionTimeoutMS: 5000,
heartbeatFrequencyMS: 10000,
retryWrites: true,
retryReads: true
});
console.log('レプリカセットに接続完了');
// レプリカセットステータスを監視
const admin = mongoose.connection.db.admin();
const status = await admin.command({ replSetGetStatus: 1 });
console.log('レプリカセットステータス:');
status.members.forEach(m => {
console.log(` ${m.name}: ${m.stateStr} (health: ${m.health})`);
});
// 現在のPrimary
const primary = status.members.find(m => m.stateStr === 'PRIMARY');
console.log(`現在のPrimary: ${primary?.name}`);
} catch (err) {
console.error('接続失敗:', err.message);
console.log('5秒後にリトライ...');
setTimeout(connectWithRetry, 5000);
}
}
// 接続イベント処理
mongoose.connection.on('disconnected', () => {
console.log('MongoDBから切断');
});
mongoose.connection.on('reconnected', () => {
console.log('MongoDBに再接続');
});
mongoose.connection.on('error', (err) => {
console.error('MongoDB接続エラー:', err);
});
connectWithRetry();
出力:
TEXT 📖 参照専用レプリカセットに接続完了 レプリカセットステータス: mongo1:27017: PRIMARY (health: 1) mongo2:27017: SECONDARY (health: 1) mongo3:27017: SECONDARY (health: 1) 現在のPrimary: mongo1:27017
❓ よくある質問
📖 まとめ
- レプリカセット:Primary + Secondary + Arbiter
- 選挙メカニズム:Raftベース、過半数票が必要
- データ同期:初期同期 + oplog追跡
- 読み書き分離:readPreference
- Dockerでの3ノード構築
- フェイルオーバー:自動選挙 + アプリ再接続
📝 練習問題
- 基礎問題(⭐): Docker Composeで3ノードレプリカセットをデプロイ。
- 基礎問題(⭐): レプリカセットを初期化し、ステータスを確認(rs.status())。
- 応用問題(⭐⭐): 読み書き分離をテスト(readPreference: secondary)。
- 応用問題(⭐⭐): Primary障害をシミュレートし、自動選挙プロセスを観察。
- チャレンジ(⭐⭐⭐): 完全なレプリカセットをデプロイ(3ノード + レプリカセット監視 + 障害復旧テスト)。