コンピューターサイエンス:アルゴリズム / OS / ネットワーク / DB

レプリケーション

生田 陸人
LuaGate エンジニア / 現役エンジニア
編集 LuaGate編集部

レプリケーション

このレッスンで分かること

  • Primary / Replica 構成の役割分担
  • 同期・準同期・非同期レプリケーションの違い
  • レプリカラグが引き起こす問題と対策

レプリケーション とは

Primary / Replica 構成での読み取り分散と整合性。本レッスンでは、レプリケーション の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

レプリケーションとは

レプリケーション (Replication) とは、1 台のデータベース (Primary) の変更を 複数のコピー (Replica) にリアルタイムに反映する仕組みです。

目的は次の 3 つです。

  • 読み取りスケール — Replica に SELECT を分散
  • 可用性 — Primary が落ちても Replica が引き継げる (Failover)
  • バックアップ・分析用途 — Replica で重い分析クエリを走らせる
diagram (will load when visible)

どう同期されるか

Primary の変更は WAL (Write-Ahead Log)Binlog (MySQL) という変更ログに記録され、これを Replica に転送して 再適用 することで同期します。

ログ転送方式は次の 2 系統があります。

  • 物理レプリケーション — ディスクページの変更そのものを転送 (PostgreSQL のストリーミングレプリケーション)
  • 論理レプリケーション — SQL 文や行変更を転送 (PostgreSQL の publication/subscription、MySQL のレプリケーション全般。Row-based・Statement-based はいずれも binlog を用いた論理レプリケーション)

物理は速いが Primary と Replica のバージョンを揃える必要があり、論理は遅いがバージョン差や部分レプリカに柔軟。

3 つのモード

同期レプリケーション (Synchronous)

Primary は 全 Replica が書き込み完了するまで COMMIT を待ちます。

  • 一貫性は完璧(コミット済みデータは必ず全 Replica にある)
  • 1 台でも遅い Replica があれば全体が遅くなる
  • ネットワーク障害で Primary も止まる

金融や予約システムなど、整合性が最優先の場面で使います。

準同期 (Semi-Synchronous)

Primary は 少なくとも N 台の Replica が受信した時点で COMMIT 完了とします。MySQL の準同期はこの方式で、よく N=1 で運用されます。

  • パフォーマンスと安全性のバランスが良い
  • 1 台落ちても残りで継続可能

非同期 (Asynchronous)

Primary は WAL を送信したらすぐ COMMIT 完了。Replica は遅れて追いつきます。

  • 速い(Primary の性能ほぼそのまま)
  • Primary 障害時、未転送分が失われる可能性
  • レプリカラグが発生する

デフォルトのレプリケーションはほぼ非同期です。

レプリカラグの問題

非同期で起きるのが レプリカラグ (Replication Lag) です。Primary に書いた直後に Replica から読むと、まだ反映されておらず古いデータが返ります。

プレーンテキスト

T1: Primary INSERT user (name='Alice') -- 成功 T2: Replica SELECT user WHERE name='Alice' -- 0 件 ← ラグで未到着

これでユーザーの登録直後に「ユーザーが見つかりません」というエラーが起きると体験が壊れます。

対策

  • 書き込み直後の読み取りは Primary に向ける — セッションごとに「書き込みフラグ」を持ち、その後の SELECT は Primary
  • 同期 / 準同期に切り替える — 遅延を許容できない場面
  • Read Your Writes 保証 — ユーザー本人の書き込みは本人が確実に読めるよう、専用ロジックを書く
  • アプリ側で再試行 — 数百ミリ秒待って再 SELECT

レプリカラグは「ある」前提で設計する。「ない」前提だと事故る。

フェイルオーバー

Primary が落ちたら Replica の 1 つを Primary に昇格 させます。これを フェイルオーバー と呼びます。

自動フェイルオーバーには専用ツールが必要です。

  • PostgreSQL — Patroni、repmgr
  • MySQL — MHA、Orchestrator、ProxySQL
  • クラウド — RDS の Multi-AZ、Aurora の自動フェイルオーバー

フェイルオーバー時には、未転送のトランザクションが失われたり、DNS / IP の切り替えに数秒〜数分かかります。

読み書き分離

アプリ側で「書き込みは Primary、読み取りは Replica」と振り分けるのが定石です。

JavaScript

const writePool = mysql.createPool({ host: 'primary.example.com' }); const readPool = mysql.createPool({ host: 'replica.example.com' }); await writePool.query('INSERT INTO ...'); const rows = await readPool.query('SELECT FROM ...');

ORM やルーター(ProxySQLPgBouncer)が透過的に振り分ける機能もあります。

カスケードレプリケーション

Replica からさらに別の Replica にレプリケーションする構成です。

プレーンテキスト

Primary → Replica A → Replica A の子 Replica

Primary の負荷を抑えられる一方、ラグが二重になります。地理分散構成でよく使われます。

やってみよう

  • Docker Compose で MySQL の Primary 1 台 + Replica 1 台を立てる
  • Primary に INSERT し、Replica で SELECT して反映時間を計測する
  • Replica の SHOW REPLICA STATUS (旧 SHOW SLAVE STATUS) で Seconds_Behind_Source を確認する

よくある質問

Q. このトピックは実務でどう役立ちますか?

A. DB のクエリ最適化、API 設計、データ構造の選択など、設計判断の根拠になります。表面的にライブラリを使うだけでなく「なぜそれが速いのか」を理解できると、性能問題を未然に防げます。コーディング面接でも頻出のテーマです。

Q. 計算量はどう求めれば良いですか?

A. ループのネストごとに掛け算する、再帰なら漸化式から解く、というのが基本です。Big-O 表記は定数倍と低次の項を無視するため、n の指数(n²、n log n など)に注目してください。最悪・平均・最良の 3 つを意識すると説得力が増します。

Q. 覚えるべき定番アルゴリズムは何ですか?

A. 二分探索、クイックソート/マージソート、BFS/DFS、ダイクストラ、DP の基本問題(フィボナッチ・ナップサック)が必修です。これらを「白紙から書ける」状態にすると、応用問題が一気に解けるようになります。

次のレッスン

次は シャーディング で、Primary / Replica 構成での読み取り分散と整合性 を学びます。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. レプリケーション の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. レプリケーション とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン