🔁
レプリケーション
同じデータを複数ノードに保持する方法。シングルリーダー・マルチリーダー・リーダーレスの3方式と、レプリケーション遅延が生む一貫性の問題を理解する
定義
レプリケーション:同じデータを、ネットワークで接続された複数のマシンに保持すること。
目的:
- 地理的にユーザーに近いデータ(低レイテンシ)
- 一部のノードが故障しても継続稼働(可用性)
- 読み取りクエリを複数ノードに分散(スループット向上)
3つのレプリケーション方式
シングルリーダー(Single-Leader)
書き込みは1ノードのみ受け付ける。最もシンプル。
マルチリーダー(Multi-Leader)
複数ノードが書き込みを受け付ける。データセンター間に使いやすい。
リーダーレス(Leaderless / Dynamo-style)
すべてのノードが書き込みを受け付ける。CassandraやDynamo。
シングルリーダーレプリケーション
クライアント
│ 書き込み
▼
リーダー(プライマリ)
├─── レプリケーションログ ──→ フォロワー1
└─────────────────────────→ フォロワー2
読み取り: リーダー or フォロワー
同期 vs 非同期レプリケーション
| 方式 | 動作 | 保証 | リスク |
|---|---|---|---|
| 同期 | フォロワー確認後に書き込み完了 | 耐久性高い | リーダーが遅いフォロワーを待つ |
| 非同期 | フォロワーの確認を待たない | 高速 | フォロワーが遅れうる(Lag) |
| 半同期 | 1つのフォロワーだけ同期 | バランス型 | 実用的な妥協点 |
レプリケーション遅延の問題
非同期レプリケーションでは、フォロワーが最新状態に追いついていない間に読み取りをすると古いデータが返る(最終的一貫性)。
自分の書き込みを読む(Read-your-writes):
ユーザーが自分のプロフィールを更新
→ 書き込みはリーダーへ
→ 直後に読み取りがフォロワーへ
→ 古いプロフィールが表示される(ユーザーの書き込みが「消えた」ように見える)
対策:自分のデータを読む時はリーダーから読む。最後の書き込み時刻をクライアントが持ち、それ以降の更新が来るまでリーダーに向ける。
モノトニックな読み取り(Monotonic reads):
ユーザーAがコメントを投稿
フォロワー1 → コメントあり(進んでいる)
フォロワー2 → コメントなし(遅れている)
同じユーザーBが交互にアクセスすると、コメントが「消えたり出たり」する
対策:同一ユーザーは常に同じフォロワーに向ける(ユーザーIDのハッシュで振り分け)。
マルチリーダーレプリケーション
複数のデータセンターに書き込みを受け付けるリーダーを配置。
データセンター A データセンター B
リーダーA ←────────→ リーダーB
フォロワー フォロワー
ユーザーは最寄りのデータセンターに書き込む
書き込み競合(Write Conflict):
UserA が title を "A" に変更 → リーダーA
UserB が title を "B" に変更 → リーダーB(同時に)
どちらが正しいか自動では決められない。競合解決戦略:
- Last Write Wins(LWW):タイムスタンプで最後を勝者に(精度問題あり)
- On Read:競合をすべて保存し、読み取り時にアプリが解決
- On Write:書き込みハンドラで解決ロジックを実装
- CRDT(Conflict-free Replicated Data Type):数学的に競合しないデータ構造
リーダーレスレプリケーション(Dynamo-style)
Amazon DynamoDBやCassandraが採用。**クォーラム(Quorum)**で一貫性を確保。
n = 総レプリカ数
w = 書き込み確認が必要なノード数
r = 読み取りで参照するノード数
w + r > n ならば、読み取りは必ず最新の書き込みを含む少なくとも1ノードを参照する
例:n=3, w=2, r=2
書き込み: 3ノードのうち2つの確認でOK
読み取り: 3ノードのうち2つを参照 → バージョン番号で最新を選ぶ
リードリペア vs アンチエントロピー
- リードリペア:読み取り時に古いレプリカを発見したら更新
- アンチエントロピー:バックグラウンドプロセスが差分を常に同期
クォーラムは「強い一貫性の保証」ではない。同時書き込みの競合などでセーフガードをすり抜けることがある。
フェイルオーバーの難しさ
シングルリーダーでリーダーが死んだ場合:
- リーダー障害の検知(タイムアウト)
- 新しいリーダーの選出(最新のフォロワーを昇格)
- クライアントの向き先変更
問題:
- 非同期レプリカが選ばれると、古いリーダーが持っていた書き込みが失われる
- スプリットブレイン:2ノードが同時にリーダーと思い込む
- タイムアウト設定が難しい(短すぎると誤検知、長すぎると回復が遅い)
関連概念
出典・参考文献
- Martin Kleppmann, Designing Data-Intensive Applications (2017) Chapter 5
- DeCandia et al., “Dynamo: Amazon’s Highly Available Key-value Store” (2007)
- 1. 🗄️データ志向アプリケーション設計:概要
- 2. 🧩データモデルとクエリ言語
- 3. 💾ストレージエンジンとインデックス
- 4. 🔁レプリケーション
- 5. 🍕パーティショニング(シャーディング)
- 6. 🔒トランザクションとACID
- 7. ⚡分散システムの本質的な問題
- 8. 🤝一貫性と分散合意
- 9. 📦バッチ処理
- 10. 🌊ストリーム処理
- 11. 📋エンコーディングとスキーマ進化
- 12. 🔗Sagaパターンと分散トランザクション
- 13. 🏗️データシステムの統合設計
出典: Martin Kleppmann, 'Designing Data-Intensive Applications' (2017) Chapter 5