PostgreSQLレプリケーションのマスター:タイプとセットアップの説明

PostgreSQLのストリーミングレプリケーションとロジカルレプリケーションの仕組み、それぞれの使用場面、そして本番環境でのフェイルオーバー前に確認すべき事項について学びます。

PostgreSQLレプリケーションの習得:種類とセットアップの解説

PostgreSQLレプリケーションは、セカンダリサーバーをプライマリに十分近い状態に保つことで、ハードウェア障害を乗り越えたり、読み取りトラフィックを分散したり、制御された移行を実行したりすることを可能にします。データベースが本番環境の依存関係である場合、ノードが障害を起こす前に、どのPostgreSQLレプリケーションモデルがリスク許容度に合っているかを知っておく必要があります。

PostgreSQLには、ストリーミングレプリケーションとロジカルレプリケーションという2つの一般的な選択肢があります。ストリーミングレプリケーションは、物理クラスターレベルでWALをコピーします。ロジカルレプリケーションは、パブリケーションとサブスクリプションを通じて、選択したテーブルから行レベルの変更を送信します。

PostgreSQLレプリケーションが重要な理由

レプリケーションは、4つの日常的な運用上の問題を解決するのに役立ちます。

  • 高可用性: プライマリが障害を起こした場合、スタンバイを昇格させてアプリケーションをそのスタンバイに向けることができます。
  • ディザスタリカバリ: 別の場所にあるスタンバイは、サイトレベルの障害から保護することができます。
  • 読み取りスケーリング: 読み取り専用クエリを書き込みプライマリの代わりにホットスタンバイに対して実行できます。
  • 移行サポート: ロジカルレプリケーションは、PostgreSQLのバージョン間やデータベースレイアウト間で選択したテーブルを移動するのに役立ちます。

レプリケーションはバックアップの代替にはなりません。バグ、誤ったマイグレーション、または偶発的なDELETEはすぐにレプリケートされる可能性があります。レプリケーションと並行して、テスト済みのバックアップとポイントインタイムリカバリを維持してください。

ストリーミングレプリケーション(物理レプリケーション)

ストリーミングレプリケーションは、PostgreSQLで最も一般的で基本的なレプリケーションの形式です。これは、プライマリサーバーから1つ以上のレプリカに先行書き込みログ(WAL)レコードを送信することで機能します。これらのWALレコードは、データベースに加えられたすべての変更を表します。レプリカはこれらのWALレコードを自身のデータファイルに適用し、プライマリとの一貫性を保ちます。

同期ストリーミングと非同期ストリーミング

同期レプリケーションでは、プライマリは1つ以上の同期スタンバイを待ってから、クライアントにコミットを報告します。正確な安全性のレベルはsynchronous_commitに依存します。例えば、WALが書き込まれるのを待つことは、WALが再生されるのを待つこととは異なります。承認されたコミットが失われることに対する強力な保護が得られますが、すべてのコミットがレプリカとネットワークのレイテンシに依存するようになります。

非同期レプリケーションでは、プライマリはローカルでコミットし、その後WALをレプリカに送信します。書き込みは高速ですが、プライマリがクラッシュすると、まだスタンバイに到達していなかった最近のトランザクションが失われる可能性があります。

ストリーミングレプリケーションのセットアップ(非同期の例)

ストリーミングレプリケーションのセットアップには、プライマリサーバーとレプリカサーバーの両方の設定が含まれます。以下は簡略化したガイドです。

1. プライマリサーバーの設定(postgresql.confpg_hba.conf

プライマリサーバーでは、WALアーカイブとレプリケーション接続を有効にする必要があります。

  • postgresql.conf の変更点:

    wal_level = replica  # ロジカルレプリケーションの場合は logical
    max_wal_senders = 5  # 同時レプリケーション接続数
    wal_keep_size = 512MB # 古いバージョンでは wal_keep_segments
    # 同期レプリケーションの場合は、以下を追加:
    # synchronous_standby_names = 'replica1,replica2'
    # または特定のサーバー名/優先度の場合:
    # synchronous_standby_names = '1 (replica1), 2 (replica2)'
    archive_mode = on
    archive_command = 'test ! -f /path/to/wal_archive/%f && cp %p /path/to/wal_archive/%f'
    
    • wal_level:ストリーミングレプリケーションの場合は少なくともreplicaである必要があります。
    • max_wal_senders:同時に接続できるスタンバイサーバーの数を指定します。
    • wal_keep_size:レプリカが取得する前にWALファイルが削除されるのを防ぎます(基本的なセットアップではarchive_commandのより単純な代替手段ですが、堅牢性のためにアーカイブが推奨されます)。
    • archive_modearchive_command:ポイントインタイムリカバリ(PITR)や、遅延後に古いWALを必要とするレプリカに役立ちます。本番環境では、ローカルコピーコマンドの代わりに実際のアーカイブターゲットまたはバックアップツールを使用してください。
  • pg_hba.conf の変更点:

    レプリカがレプリケーションのために接続できるようにします。replica_ip_addressをレプリカの実際のIPに置き換えてください。

    # TYPE  DATABASE        USER            ADDRESS                 METHOD
    host    replication     replication_user  replica_ip_address/32   md5
    

    また、レプリケーションユーザーを作成する必要があります。

    -- プライマリサーバーで:
    CREATE ROLE replication_user WITH REPLICATION LOGIN PASSWORD 'your_password';
    

    これらのファイルを変更した後、PostgreSQL設定をリロードします。

    pg_ctl reload
    # または必要に応じてPostgreSQLを再起動
    

2. レプリカサーバーの準備

レプリカを起動する前に、特定の時点でのプライマリのデータディレクトリのコピーであるデータディレクトリが必要です。最も簡単な方法は、pg_basebackupを使用することです。

  • レプリカでPostgreSQLを停止します(実行中の場合)。

  • ベースバックアップを取得します。

    # 最初にPGDATAが空であるか削除されていることを確認
    pg_basebackup -h primary_host_ip -p 5432 -U replication_user -D /var/lib/postgresql/data/ -Fp -Xs -P -R
    
    • -h-p-U:プライマリサーバーの接続詳細を指定します。
    • -D:レプリカのデータディレクトリ。
    • -Fp:フォーマットはプレーン。
    • -Xs:バックアップ中にWALをストリーミングします。
    • -P:進行状況を表示します。
    • -R:スタンバイ接続設定を書き込み、PostgreSQL 12以降用にstandby.signalを作成します。
    • replication_userのパスワードを求められます。

3. レプリカサーバーの設定

  • postgresql.conf の変更点(PG12+の場合):

    hot_standby = on # レプリカでの読み取り専用クエリを許可
    primary_conninfo = 'host=primary_host_ip port=5432 user=replication_user password=your_password'
    
    • hot_standby:スタンバイでの読み取り専用クエリを有効にします。
    • primary_conninfo:プライマリサーバーへの接続文字列。
  • 古いPostgreSQLバージョンの場合:

    PostgreSQL 12ではrecovery.confが削除されました。古いサーバーを管理している場合は、レプリカデータディレクトリにrecovery.confを作成します。

    standby_mode = 'on'
    primary_conninfo = 'host=primary_host_ip port=5432 user=replication_user password=your_password'
    # ストリーミングの代わりにアーカイブリカバリを使用する場合は、restore_commandを指定します
    # restore_command = 'cp /path/to/wal_archive/%f %p'
    # recovery_target_timeline = 'latest'
    

    PostgreSQL 12以降では、スタンバイモードはstandby.signalによって制御され、primary_conninfoは通常、pg_basebackup -Rによって作成された場合、postgresql.auto.confに格納されます。

4. レプリカサーバーの起動

レプリカでPostgreSQLサービスを起動します。プライマリに接続し、WALレコードを受信して、同期を開始します。確認のためにログを確認できます。

ヒント: 堅牢なHAのためには、フェイルオーバーと管理を自動化するPatroniやrepmgrなどのツールの使用を検討してください。

ロジカルレプリケーション

ロジカルレプリケーションは、PostgreSQL 10で導入された、より柔軟で詳細なレプリケーション形式です。データブロック全体やWALレコードをレプリケートする代わりに、行レベルでの論理的な意味(INSERT、UPDATE、DELETEステートメントなど)に基づいてデータ変更をレプリケートします。これは、WALレコードを論理的な変更のストリームにデコードすることで実現されます。

主な機能とユースケース:

  • 選択的レプリケーション: レプリケートするテーブルを選択できます。最近のPostgreSQLバージョンでは、パブリケーションでのカラムリストもサポートされていますが、その機能に依存する前にサーバーバージョンを確認してください。
  • クロスバージョンレプリケーション: ロジカルレプリケーションは、PostgreSQLの異なるメジャーバージョン間でデータをレプリケートできます。
  • スキーマ制御: ロジカルレプリケーションはDDLを自動的にレプリケートしません。サブスクライバーに一致するテーブルを作成し、スキーママイグレーションを適用します。
  • データ変換: 組み込みではありませんが、ロジカルレプリケーションはより複雑なETL(抽出、変換、ロード)プロセスの基盤を提供します。
  • 完全なクローンではないレプリカへのプライマリからのレプリケーション: ターゲットデータベースは、ソースの完全な物理コピーである必要はありません。

仕組み:

  1. パブリッシャー: データ変更が発生するソースデータベース(プライマリ)。wal_level = logicalが必要です。変更はWALから論理ストリームにデコードされます。
  2. パブリケーション: 変更がレプリケートされるパブリッシャー上の名前付きテーブルセット。
  3. サブスクライバー: 変更を受信するターゲットデータベース(レプリカ)。
  4. サブスクリプション: サブスクライバー上の接続で、パブリッシャーに接続し、特定のパブリケーションからの変更を適用します。

ロジカルレプリケーションのセットアップ

1. パブリッシャー(プライマリサーバー)の設定

  • postgresql.conf の変更点:

    wal_level = logical
    max_replication_slots = 10 # ロジカルレプリケーションスロット用
    max_wal_senders = 10     # 少なくとも max_replication_slots 以上である必要があります
    
  • パブリケーションの作成:

    -- パブリッシャーデータベースで:
    CREATE PUBLICATION my_publication FOR TABLE 
        table1, 
        table2 
        WITH (publish = 'insert,update,delete');
    
    -- またはすべてのテーブルの場合:
    -- CREATE PUBLICATION all_tables_pub FOR ALL TABLES;
    

    パブリッシャーで設定をリロードします。

2. サブスクライバー(レプリカサーバー)の設定

  • ターゲットテーブルが存在することを確認します: サブスクライバーデータベースには、パブリッシャーと同じスキーマを持つターゲットテーブルが必要です。手動で作成するか、pg_dumpを使用してスキーマを抽出できます。

  • サブスクリプションの作成:

    -- サブスクライバーデータベースで:
    CREATE SUBSCRIPTION my_subscription
        CONNECTION 'host=publisher_host_ip port=5432 user=replication_user password=your_password dbname=publisher_db'
        PUBLICATION my_publication;
    

    replication_userはパブリッシャー上で適切な権限を持っている必要があります。

    PostgreSQLは自動的にパブリッシャー上にレプリケーションスロットを作成し、変更の適用を開始します。サブスクライバーでpg_stat_subscriptionを使用してサブスクリプションのステータスを監視できます。

ヒント: ロジカルレプリケーションは、PostgreSQLの組み込みのロジカルデコードインフラストラクチャを使用します。基本的なパブリケーションとサブスクリプションに別の拡張機能は必要ありません。

適切なレプリケーション方法の選択

  • ストリーミングレプリケーション: 高可用性ディザスタリカバリに最適で、プライマリの正確なバイトレベルのコピーが必要な場合に適しています。完全なデータベースレプリケーションのセットアップがより簡単で、読み取り専用レプリカに最適な読み取りスケーラビリティを提供します。
  • ロジカルレプリケーション: 選択的なデータ配布移行クロスバージョンアップグレード、またはデータのサブセットのみをレプリケートする必要がある場合に最適です。異なるスキーマへのレプリケーションやデータ変換の実行など、より複雑なシナリオが可能になります。

まとめ

フェイルオーバー、ディザスタリカバリ、または読み取り専用トラフィック用の完全なスタンバイが必要な場合は、ストリーミングレプリケーションを使用してください。選択したテーブル、クロスバージョン移行、または異なるデータベース間での制御されたデータ移動が必要な場合は、ロジカルレプリケーションを使用してください。

どちらのセットアップを信頼する前に、フェイルオーバードリルを実行し、アプリケーションの接続処理を確認し、レプリケーションラグを監視し、バックアップが正常に復元されることを確認してください。レプリケーションは別のサーバーを最新の状態に保ちますが、運用テストの代わりにはなりません。