せっかくの正月だし、レプリケーションについて理解しとくか

### なぜレプリケーションが必要か

1. **高可用性（障害が発生してもサービスを止めない）**  
   - 1台のマシンやデータセンター全体がダウンしても、サービスを継続できるようにする。

2. **オフラインでの操作（ネットワーク障害時の継続運用）**  
   - ネットワークが切断されてもアプリケーションを動かし続ける。

3. **レイテンシの低減（ユーザーに近い場所でデータを読む）**  
   - 地理的にユーザーの近い場所にデータを配置し、アクセスを高速化する。

4. **読み取りスケーラビリティ（読み取り負荷の分散）**  
   - 同じデータを複数のレプリカで保持しておけば、1台だけでは対応しきれない大量の読み取り処理をさばける。

---

### レプリケーションの難しさ

- **ノード障害やネットワーク障害への対応が必須**  
  - マシンが落ちる、ネットワークが切れる、といった様々なトラブルに備えなければならない。
- **ソフトウェアバグやデータ破損の可能性**  
  - じわじわとデータが壊れていく障害（バグなど）への対処はさらに難しい。

---

# 3つのレプリケーションのアプローチ

## 1. シングルリーダーレプリケーション

### 仕組み

- **1つのリーダーノード**が書き込みを集中して受け付ける。  
- リーダーがデータを更新した後、その変更を「変更イベント（変更ログなど）」として**フォロワーノード**に配信する。
- クライアントは読み取り要求をリーダーまたはフォロワーに送ることができるが、フォロワーが最新状態を反映するまでに**レプリケーションラグ**が生じることがある。

### 特徴

1. **実装・理解が比較的シンプル**  
   - 書き込み先が1つに限定されるため、データ衝突（同じデータを同時に更新してしまう問題）が発生しにくい。  
   - コンフリクト解決のロジックがほぼ不要。

2. **運用しやすい**  
   - 一般的なRDBMSや多くのNoSQLでも採用されており、運用実績が豊富。  
   - 障害時のフェイルオーバー（リーダーの切り替え）プロセスはある程度確立された方法が存在する。

3. **スケールの方向性**  
   - **読み取り**に関しては、フォロワーを増やすことで処理能力を高める（読み取りスケールアウト）。  
   - **書き込み**はリーダー1台に集まるため、リーダーのマシンスペックを上げるか、別の手法（シャーディングなど）と組み合わせる必要がある。

### 注意点

- **リーダー障害時のフェイルオーバー**  
  - リーダーがダウンしたら、フォロワーの中から新しいリーダーを選んで昇格させる必要がある。  
  - 同期・非同期のレプリケーションをどうするかで、フェイルオーバー後に最新データが消失するリスクがある（非同期レプリケーションの場合）。
  
- **レプリケーションラグによる古いデータの読み取り**  
  - フォロワーから読み取ると、書き込み直後の最新データが反映されていない可能性がある。  
  - これは、read-after-write 一貫性などの方法である程度制御できる。

---

## 2. マルチリーダーレプリケーション

### 仕組み

- **複数のリーダーノード**が存在し、どのリーダーでも書き込みを受け付ける。  
- リーダー同士が相互に変更を通知し合い、さらにフォロワーにも変更を伝播する。  
- 一般的に「アクティブ-アクティブ構成」と呼ばれることが多い。

### 特徴

1. **地理的分散への強さ**  
   - 各地域にリーダーを置き、ローカルのユーザーからの書き込みはその地域のリーダーで処理する。  
   - ネットワークの遅延を抑えやすく、アプリケーションのレスポンスを向上させる。

2. **高い可用性**  
   - どのリーダーでも書き込み可能なため、1つのリーダーが障害を起こしても、他のリーダーで書き込みが継続できる。  
   - ダウンしたノードが復旧したら、変更内容を同期する。

3. **衝突（コンフリクト）への対処が必須**  
   - 複数のリーダーで同じデータに対して同時に更新が行われると、更新内容が衝突する可能性が高い。  
   - 衝突解決の仕組み（タイムスタンプによる優先度、トランザクションログのマージ、アプリケーション固有の解決ルールなど）が必要。

### 代表的なアプリケーション例

- **オフライン編集・後からマージするコラボレーションツール**  
  - 例えば、支社が遠隔地にあるなどで一時的に接続が不安定な場合も、それぞれがローカルリーダーに書き込み、後からマージする。  
- **世界中にユーザーが散らばるSNSやチャットサービス**  
  - ユーザーが少しでも近いデータセンターに書き込むことで、操作感を高速化する。

### 注意点

- **コンフリクト解決ロジックの複雑さ**  
  - どのように衝突を検知し、どちらのデータを優先するかなど、アプリケーション固有のポリシーが必要。  
- **書き込み整合性の低下**  
  - ユーザーがどのリーダーにアクセスするかによって、データの最新状態が異なる時間帯が発生する可能性がある。  
- **運用コスト**  
  - リーダー同士の通信が増え、障害時のデバッグも複雑化する。

---

## 3. リーダーレスレプリケーション

### 仕組み

- **リーダーノードを設けず**、クライアントが直接複数のノードに対して書き込みを行う。  
- 読み取り時も複数ノードから並行にデータを取得し、最新・正しいデータを推測・修正する（**read repair**、**quorum**などの仕組み）。
- ノードが一時的にオフラインでも、後で再接続したときに自動的にデータが同期される仕組み（**hinted handoff**など）が使われることが多い。

### 特徴

1. **高い耐障害性**  
   - 個々のノードがダウンしていても、クライアントが書き込みや読み取りで十分な**応答多数（quorum）**を得られればシステムは動作を継続できる。  
   - ネットワーク障害が起きて部分的にしか接続できない場合でも、「書き込み先の一部に届いていればOK」という設計が可能。

2. **動的な負荷分散**  
   - 特定ノードへの集中が起きにくく、読み取り・書き込みの両方を複数ノードに分散できる。

3. **整合性モデルの柔軟さ**  
   - “**書き込み成功とするために何台のノードに複製が行われることを必要とするか**”を設定できる。  
   - ただし設定次第では、強い一貫性を担保できない（書き込まれていないノードがある、読み取りで古いデータを返すなどの可能性）。

### 衝突解決

- **read repair（読み取り時の修復）**  
  - 読み取り要求を行ったとき、取得した複数ノードのデータを比較し、古いデータや更新漏れを検知すると、最新データで上書きする。  
- **マージ戦略**  
  - 同時更新が起きた場合、「タイムスタンプが新しい方を優先する」「アプリケーション側で履歴をマージする」といった解決が必要。

### 代表的なシステム例

- **Amazon Dynamo系**（Cassandra、Voldemort、Riakなど）  
  - 特に大量の読み書きが発生する分散システムに向いている。
- **一部のP2Pベースのデータストア**  
  - 完全に対等なノードの集合でデータをやり取りする仕組みを採用。

### 注意点

- **一貫性の保証が弱め**  
  - 高い可用性を優先する反面、最新データを返せる保証がシングルリーダーよりも低い場合が多い。  
- **運用・トラブルシュートの難しさ**  
  - 各ノードが部分的に同期している状態が当たり前なので、どこでデータが消失や衝突を起こしたのかを調べるのが大変なこともある。

### 同期か非同期か

- **同期レプリケーション**  
  - リーダーがデータを書き込むとき、他ノードへの複製が完了するまで待つ方式。  
  - レプリカが常に最新データを持つが、書き込みの遅延が大きくなる可能性。

- **非同期レプリケーション**  
  - リーダーが更新をコミットしてから、ある程度遅れて他ノードに変更を伝える方式。  
  - 通常は高速に動くが、障害発生時に**最新データが失われるリスク**がある。

---

### レプリケーションラグと一貫性モデル

レプリケーションラグ（フォロワーにデータが伝わるまでの遅延）があると、古いデータを読み込むことがある。これをどう扱うかを示すのが**一貫性モデル**である。

1. **read-after-write 一貫性**  
   - ユーザーは**自分が書いたデータ**をすぐに読み取れるようにする。  
   - 例: SNSで投稿した直後に自分の投稿が反映される。

2. **モノトニックリード（一貫した読み取り順序）**  
   - 一度新しいデータを見たユーザーは、次の読み取りでそれより古い状態に戻らない。  
   - 例: 前回表示したフィードの履歴よりも古い投稿を再度見せない。

3. **一貫性のあるプレフィックス読み取り**  
   - **因果関係**があるイベントの順序が崩れないようにする。  
   - 例: 質問 → 回答のやり取りが正しい時系列で見えるようにする。

---

### 衝突(コンフリクト)への対処

- **マルチリーダーやリーダーレスでは、同時書き込みが発生しやすい。**  
  - 「どちらが先に書いたか」「同時書き込みか」を判定するアルゴリズムが必要。  
  - 衝突した内容をどうマージ（統合）するかが課題になる。

---

### まとめ

- レプリケーションには高可用性や低レイテンシ、スケーラビリティなど多くのメリットがある。  
- しかし、障害が起こる状況を考慮して動作を設計・実装する必要があり、非常に難しい。  
- シングルリーダーはシンプルで広く使われるが、耐障害性やレイテンシの観点ではマルチリーダー、リーダーレスにも利点がある。  
- レプリケーションラグによって生じる一貫性の問題には、read-after-writeなどのモデルを使って対処する。  
- 次章では、レプリケーションと対をなすもう一つの大きなテーマである**パーティション分割（シャーディング）**について学ぶ。

以上が、レプリケーションにおける重要なポイントの概要です。