なぜレプリケーションが必要か
-
高可用性(障害が発生してもサービスを止めない)
- 1台のマシンやデータセンター全体がダウンしても、サービスを継続できるようにする。
-
オフラインでの操作(ネットワーク障害時の継続運用)
- ネットワークが切断されてもアプリケーションを動かし続ける。
-
レイテンシの低減(ユーザーに近い場所でデータを読む)
- 地理的にユーザーの近い場所にデータを配置し、アクセスを高速化する。
-
読み取りスケーラビリティ(読み取り負荷の分散)
- 同じデータを複数のレプリカで保持しておけば、1台だけでは対応しきれない大量の読み取り処理をさばける。
レプリケーションの難しさ
-
ノード障害やネットワーク障害への対応が必須
- マシンが落ちる、ネットワークが切れる、といった様々なトラブルに備えなければならない。
-
ソフトウェアバグやデータ破損の可能性
- じわじわとデータが壊れていく障害(バグなど)への対処はさらに難しい。
3つのレプリケーションのアプローチ
1. シングルリーダーレプリケーション
仕組み
- 1つのリーダーノードが書き込みを集中して受け付ける。
- リーダーがデータを更新した後、その変更を「変更イベント(変更ログなど)」としてフォロワーノードに配信する。
- クライアントは読み取り要求をリーダーまたはフォロワーに送ることができるが、フォロワーが最新状態を反映するまでにレプリケーションラグが生じることがある。
特徴
-
実装・理解が比較的シンプル
- 書き込み先が1つに限定されるため、データ衝突(同じデータを同時に更新してしまう問題)が発生しにくい。
- コンフリクト解決のロジックがほぼ不要。
-
運用しやすい
- 一般的なRDBMSや多くのNoSQLでも採用されており、運用実績が豊富。
- 障害時のフェイルオーバー(リーダーの切り替え)プロセスはある程度確立された方法が存在する。
-
スケールの方向性
- 読み取りに関しては、フォロワーを増やすことで処理能力を高める(読み取りスケールアウト)。
- 書き込みはリーダー1台に集まるため、リーダーのマシンスペックを上げるか、別の手法(シャーディングなど)と組み合わせる必要がある。
注意点
-
リーダー障害時のフェイルオーバー
- リーダーがダウンしたら、フォロワーの中から新しいリーダーを選んで昇格させる必要がある。
- 同期・非同期のレプリケーションをどうするかで、フェイルオーバー後に最新データが消失するリスクがある(非同期レプリケーションの場合)。
-
レプリケーションラグによる古いデータの読み取り
- フォロワーから読み取ると、書き込み直後の最新データが反映されていない可能性がある。
- これは、read-after-write 一貫性などの方法である程度制御できる。
2. マルチリーダーレプリケーション
仕組み
- 複数のリーダーノードが存在し、どのリーダーでも書き込みを受け付ける。
- リーダー同士が相互に変更を通知し合い、さらにフォロワーにも変更を伝播する。
- 一般的に「アクティブ-アクティブ構成」と呼ばれることが多い。
特徴
-
地理的分散への強さ
- 各地域にリーダーを置き、ローカルのユーザーからの書き込みはその地域のリーダーで処理する。
- ネットワークの遅延を抑えやすく、アプリケーションのレスポンスを向上させる。
-
高い可用性
- どのリーダーでも書き込み可能なため、1つのリーダーが障害を起こしても、他のリーダーで書き込みが継続できる。
- ダウンしたノードが復旧したら、変更内容を同期する。
-
衝突(コンフリクト)への対処が必須
- 複数のリーダーで同じデータに対して同時に更新が行われると、更新内容が衝突する可能性が高い。
- 衝突解決の仕組み(タイムスタンプによる優先度、トランザクションログのマージ、アプリケーション固有の解決ルールなど)が必要。
代表的なアプリケーション例
-
オフライン編集・後からマージするコラボレーションツール
- 例えば、支社が遠隔地にあるなどで一時的に接続が不安定な場合も、それぞれがローカルリーダーに書き込み、後からマージする。
-
世界中にユーザーが散らばるSNSやチャットサービス
- ユーザーが少しでも近いデータセンターに書き込むことで、操作感を高速化する。
注意点
-
コンフリクト解決ロジックの複雑さ
- どのように衝突を検知し、どちらのデータを優先するかなど、アプリケーション固有のポリシーが必要。
-
書き込み整合性の低下
- ユーザーがどのリーダーにアクセスするかによって、データの最新状態が異なる時間帯が発生する可能性がある。
-
運用コスト
- リーダー同士の通信が増え、障害時のデバッグも複雑化する。
3. リーダーレスレプリケーション
仕組み
- リーダーノードを設けず、クライアントが直接複数のノードに対して書き込みを行う。
- 読み取り時も複数ノードから並行にデータを取得し、最新・正しいデータを推測・修正する(read repair、quorumなどの仕組み)。
- ノードが一時的にオフラインでも、後で再接続したときに自動的にデータが同期される仕組み(hinted handoffなど)が使われることが多い。
特徴
-
高い耐障害性
- 個々のノードがダウンしていても、クライアントが書き込みや読み取りで十分な**応答多数(quorum)**を得られればシステムは動作を継続できる。
- ネットワーク障害が起きて部分的にしか接続できない場合でも、「書き込み先の一部に届いていればOK」という設計が可能。
-
動的な負荷分散
- 特定ノードへの集中が起きにくく、読み取り・書き込みの両方を複数ノードに分散できる。
-
整合性モデルの柔軟さ
- “書き込み成功とするために何台のノードに複製が行われることを必要とするか”を設定できる。
- ただし設定次第では、強い一貫性を担保できない(書き込まれていないノードがある、読み取りで古いデータを返すなどの可能性)。
衝突解決
-
read repair(読み取り時の修復)
- 読み取り要求を行ったとき、取得した複数ノードのデータを比較し、古いデータや更新漏れを検知すると、最新データで上書きする。
-
マージ戦略
- 同時更新が起きた場合、「タイムスタンプが新しい方を優先する」「アプリケーション側で履歴をマージする」といった解決が必要。
代表的なシステム例
-
Amazon Dynamo系(Cassandra、Voldemort、Riakなど)
- 特に大量の読み書きが発生する分散システムに向いている。
-
一部のP2Pベースのデータストア
- 完全に対等なノードの集合でデータをやり取りする仕組みを採用。
注意点
-
一貫性の保証が弱め
- 高い可用性を優先する反面、最新データを返せる保証がシングルリーダーよりも低い場合が多い。
-
運用・トラブルシュートの難しさ
- 各ノードが部分的に同期している状態が当たり前なので、どこでデータが消失や衝突を起こしたのかを調べるのが大変なこともある。
同期か非同期か
-
同期レプリケーション
- リーダーがデータを書き込むとき、他ノードへの複製が完了するまで待つ方式。
- レプリカが常に最新データを持つが、書き込みの遅延が大きくなる可能性。
-
非同期レプリケーション
- リーダーが更新をコミットしてから、ある程度遅れて他ノードに変更を伝える方式。
- 通常は高速に動くが、障害発生時に最新データが失われるリスクがある。
レプリケーションラグと一貫性モデル
レプリケーションラグ(フォロワーにデータが伝わるまでの遅延)があると、古いデータを読み込むことがある。これをどう扱うかを示すのが一貫性モデルである。
-
read-after-write 一貫性
- ユーザーは自分が書いたデータをすぐに読み取れるようにする。
- 例: SNSで投稿した直後に自分の投稿が反映される。
-
モノトニックリード(一貫した読み取り順序)
- 一度新しいデータを見たユーザーは、次の読み取りでそれより古い状態に戻らない。
- 例: 前回表示したフィードの履歴よりも古い投稿を再度見せない。
-
一貫性のあるプレフィックス読み取り
- 因果関係があるイベントの順序が崩れないようにする。
- 例: 質問 → 回答のやり取りが正しい時系列で見えるようにする。
衝突(コンフリクト)への対処
-
マルチリーダーやリーダーレスでは、同時書き込みが発生しやすい。
- 「どちらが先に書いたか」「同時書き込みか」を判定するアルゴリズムが必要。
- 衝突した内容をどうマージ(統合)するかが課題になる。
まとめ
- レプリケーションには高可用性や低レイテンシ、スケーラビリティなど多くのメリットがある。
- しかし、障害が起こる状況を考慮して動作を設計・実装する必要があり、非常に難しい。
- シングルリーダーはシンプルで広く使われるが、耐障害性やレイテンシの観点ではマルチリーダー、リーダーレスにも利点がある。
- レプリケーションラグによって生じる一貫性の問題には、read-after-writeなどのモデルを使って対処する。
- 次章では、レプリケーションと対をなすもう一つの大きなテーマである**パーティション分割(シャーディング)**について学ぶ。
以上が、レプリケーションにおける重要なポイントの概要です。