🔄

データベースレプリケーション - 可用性とスケーラビリティの実現

15分 で読める | 2025.12.15

レプリケーションとは

レプリケーション(Replication)は、データベースのデータを複数のサーバーにコピーして同期する仕組みです。可用性の向上、読み取り性能の向上、災害対策などの目的で使用されます。

なぜ必要か: 単一のデータベースサーバーは単一障害点(SPOF)となります。レプリケーションにより、障害時もサービスを継続でき、読み取りクエリを分散できます。

レプリケーションの基本構成

マスター・スレーブ(プライマリ・レプリカ)

flowchart TB
    M["Master (Primary)<br/>← 書き込み"]
    M -->|レプリケーション| S1["Slave 1 (Replica)<br/>← 読み取り"]
    M -->|レプリケーション| S2["Slave 2 (Replica)<br/>← 読み取り"]
    M -->|レプリケーション| S3["Slave 3 (Replica)<br/>← 読み取り"]
  • Master(Primary): 書き込みを受け付ける主サーバー
  • Slave(Replica): マスターのデータをコピーし、読み取りを担当

マルチマスター

flowchart LR
    M1["Master 1"] <-->|レプリケーション| M2["Master 2"]
    M1 --> RW1["読み書き"]
    M2 --> RW2["読み書き"]

複数のマスターが書き込みを受け付けます。コンフリクト解決が課題となります。

同期 vs 非同期レプリケーション

同期レプリケーション

sequenceDiagram
    participant C as クライアント
    participant M as Master
    participant S as Slave
    C->>M: 書き込み
    M->>S: レプリケーション
    S->>M: ACK
    M->>C: 応答
メリットデメリット
データ損失なしレイテンシが増加
強い整合性スレーブ障害で書き込み停止

非同期レプリケーション

sequenceDiagram
    participant C as クライアント
    participant M as Master
    participant S as Slave
    C->>M: 書き込み
    M->>C: 応答
    M-->>S: レプリケーション(後から適用)
メリットデメリット
低レイテンシレプリケーションラグ
スレーブ障害の影響なしデータ損失の可能性

半同期レプリケーション

少なくとも1つのスレーブがデータを受信したらコミットを確定します。

sequenceDiagram
    participant C as クライアント
    participant M as Master
    participant S1 as Slave 1
    participant S2 as Slave 2
    C->>M: 書き込み
    M->>S1: レプリケーション
    S1->>M: ACK
    M->>C: 応答
    M-->>S2: レプリケーション(後から適用)

レプリケーションの方式

ステートメントベース

SQLステートメント自体をレプリケートします。

-- マスターで実行
INSERT INTO users (name, created_at) VALUES ('Alice', NOW());

-- スレーブでも同じSQLを実行
-- 問題: NOW()の結果が異なる可能性

行ベース

変更された行のデータ自体をレプリケートします。

flowchart LR
    Before["{id: 1, name: 'Alice'}"] --> Change["変更"] --> After["{id: 1, name: 'Bob'}"]
    After --> Apply["この差分をスレーブに適用"]

混合モード

通常はステートメントベース、非決定的な関数を含む場合は行ベースを使用します。

レプリケーションラグ

スレーブがマスターに追いつくまでの遅延です。

flowchart LR
    subgraph Master["マスター"]
        MT["トランザクション 1, 2, 3, 4, 5 ✓"]
    end
    subgraph Slave["スレーブ(ラグ: 2トランザクション分)"]
        ST["トランザクション 1, 2, 3 ✓"]
    end
    Master -.-> Slave

ラグが問題になるケース

// 書き込み後すぐに読み取り
await db.master.query('UPDATE users SET name = ? WHERE id = ?', ['Bob', 1]);

// スレーブから読み取り → 古いデータが返る可能性
const user = await db.slave.query('SELECT * FROM users WHERE id = ?', [1]);
// user.name が 'Alice' のまま!

対策

  • Read Your Writes: 書き込み直後はマスターから読み取る
  • Causal Consistency: 書き込みのタイムスタンプを追跡
  • 同期レプリケーション: 重要なデータのみ

フェイルオーバー

マスターに障害が発生した場合、スレーブをマスターに昇格させます。

自動フェイルオーバー

flowchart TB
    A["1. マスター障害検知<br/>監視システムがマスターの応答なしを検知"]
    B["2. スレーブ選出<br/>最もレプリケーションが進んでいるスレーブを選択"]
    C["3. 昇格処理<br/>選出されたスレーブをマスターに昇格"]
    D["4. 切り替え<br/>アプリケーションの接続先を新マスターに変更"]
    A --> B --> C --> D

フェイルオーバー時の注意点

課題対策
スプリットブレインフェンシング(旧マスターを強制停止)
データ損失非同期レプリの未適用トランザクション
接続切り替え仮想IP、DNS更新、プロキシ

代表的な実装

MySQL

-- マスター設定
CHANGE MASTER TO
  MASTER_HOST='master.example.com',
  MASTER_USER='repl_user',
  MASTER_PASSWORD='password',
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=4;

START SLAVE;

PostgreSQL

# postgresql.conf (マスター)
wal_level = replica
max_wal_senders = 3

# recovery.conf (スレーブ)
standby_mode = 'on'
primary_conninfo = 'host=master.example.com port=5432'

マネージドサービス

サービスレプリカ機能
Amazon RDSリードレプリカ、Multi-AZ
Cloud SQLリードレプリカ、高可用性構成
Azure SQLgeo-replication

読み取りスケーリングのパターン

flowchart LR
    App["アプリ"]
    App --> M["Master<br/>(書き込み)"]
    App --> LB["Load Balancer"]
    LB --> R1["Replica 1"]
    LB --> R2["Replica 2"]
    LB --> R3["Replica 3"]

    subgraph Read["読み取り"]
        R1
        R2
        R3
    end

ロードバランサーで読み取りクエリをレプリカに分散します。

まとめ

データベースレプリケーションは、高可用性と読み取りスケーラビリティを実現するための基盤技術です。同期/非同期の選択、レプリケーションラグへの対処、フェイルオーバー戦略を適切に設計することで、堅牢なデータベースシステムを構築できます。

← 一覧に戻る