どんな事でもお気軽にお問い合わせください
06-6567-0924

MySQLユーザー目線で設定するPostgreSQLのレプリケーション設定


こんにちは。
開発チームのワイルド担当、まんだいです。

PostgreSQL9.4で同期レプリケーションを利用する際の設定に関してまとめます。
弊社では普段MySQLを利用する事が多い状況でのPostgreSQL利用ということで
同じRDBMSとはいえど、戸惑いもありつつの作業でした。

思いの外、素直に動いてくれてとても気分が良かったので
皆さんも使ってみてはいかがでしょうかという感じでまとめてみたいと思います。

今回は少し作業工程が長く複雑ですので、お品書きをさらしておきます。

PostgreSQLのレプリケーション (マスターDB側の作業)

  1. レプリケーションユーザーを作成する
  2. pg_hba.confへの追記
  3. postgresql.confの編集
  4. マスターDBの再起動

スレーブDB側の作業

  1. pg_basebackupでマスターをコピーする
  2. postgresql.confの編集(スレーブ側)
  3. recovery.confの作成
  4. recovery.confの編集
  5. スレーブDBの再起動

レプリケーションの確認

以上の手順で進めたいと思います。

 

PostgreSQLのレプリケーション (マスターDB側の作業)

今回は既に絶賛稼働中のDBに対してレプリケーションを設定していくという
まさにワイルドな状況で作業を進めました。
余談ですが、こういう状況の方が、かえって燃えますね。

大まかな作業としては

  • マスターDB側の設定を済ませて再起動
  • スレーブDB側にマスターDBのデータをコピー
  • スレーブDB側の設定を入れて再起動
  • という形になるかと思います。

    想定として、ローカルネットワーク内のマスターDBには192.168.1.1、スレーブDBには192.168.1.2のIPアドレスが振られているという事にします。

     

    レプリケーションユーザーを作成する

    まずは簡単なところから、レプリケーション用にrepl_userというユーザーの作成を行います。
    マスターDBにログインした後、以下のクエリでユーザーを作成します。

    CREATE USER repl_user REPLICATION PASSWORD '[パスワード]';

     

    pg_hba.confへの追記

    続いて、pg_hba.confの編集を行います。
    ここでは、スレーブDBから先ほど作成したrepl_userユーザーを使って作業ができるようにします。

    host    replication repl_user   192.168.1.2/32  md5

     
    IPアドレスはスレーブのものに変更します。
    IPマスクは複数台のスレーブDBを作成する場合はそれなりにIPマスクをいじる必要もありますが
    1台のみの場合は/32で問題ないかと思います。

     

    postgresql.confの編集

    続いて、postgresql.confの編集に移ります。
    ここでは、レプリケーションに関する設定を追加・変更していきます。
    必要な設定項目は、全てコメントアウトされているので、アンコメントする事で項目を有効化できます。
    この辺はMySQLよりも親切ですね。

    レプリケーションのために必要な設定項目は以下のものになります。

     

    wal_level

    walファイルにどれだけ情報を載せるかの度合いを設定する項目です。

    walレベルは3段階あり、minimal、archive、hot_standbyになります。
    デフォルトはminimalで、通常の稼働時には、これで問題ありません。

    レプリケーションを設定する場合は、archive以上のレベルが必要なので、今回はhot_standbyに設定します。

    wal_level = hot_standby

     

    synchronous_commit

    トランザクション実行完了後、クライアントにsuccessを返す時、walファイルの書き込み完了を待つかどうかの設定です。

    デフォルトはonで、walファイルが書き込まれた後にクライアントへの応答を返します。

    offにすると、walファイルへの書き込みが失敗した場合にトランザクションデータの消失が発生し、クライアント側へ通知したステータスとは異なった結果になります。
    ただ、データ的には、トランザクション中のデータがなくなるだけで、不整合が起こる訳ではありません。

    クライアント側にsuccessを返したけれど、実際はsuccessではないという問題が発生しうるという事です。

    クライアント側への応答速度は向上しますが、たまに(そのたまにがどの程度なのかはトランザクションの失敗する程度による)ウソを返すようになるという問題だけのようです(だけなのか?)。

    今回はonにしておきます。

    synchronous_commit = on

     

    archive_mode

    アーカイブモードをonにすると、通常のwal保存領域とは違う領域にwalファイルを保存しておく事ができます。

    レプリケーションの遅延が発生した場合、スレーブ側は未適用のwalファイルを順に追いかける事になります。
    ただ、デフォルトの保存領域にあるwalファイルのライフサイクルは意外に短いので、長時間の遅延には耐えられません。
    そうなると、リカバリできないほどの遅延が発生した場合は、データの再投入をする必要があり、運用に手間が掛かります。

    それを解決するために、デフォルトの保存領域外にwalファイルをコピーする事で、ライフサイクルに左右されず、長時間のレプリケーション遅延に対応できるようにします。

    コピーされたwalファイルですが、溜まり続けるという事はない(遅延が発生した場合は残り続けるので要注意)ので、別途バッチでrmする必要はありません。
    今回はonにしておきます。

    archive_mode = on

     

    archive_command

    archive_mode = onの場合、walファイルを保存するためのコマンドを設定します。通常cpコマンドで対応する事になるかと思います。

    コマンド内で使える、コピー元のwalファイルを示す置換用文字列が幾つかありますので、それを使います。

    • %f ・・・ walファイルのファイル名
    • %p ・・・ 作業対象のwalファイルの絶対パス
    archive_command = '[walファイルを保存するためのコンソールコマンド]'

     

    max_wal_senders

    接続するスレーブDBの数を設定します。
    pg_basebackupコマンド経由の接続用にスレーブDBの数 + 1とする事が多いようです。

    max_wal_senders = 2 # slaveの数+1

     

    synchronous_standby_names

    スレーブとして接続するDB名を列挙します。
    ここに記載がない名前を持つスレーブとの接続はできないようになっています。

    synchronous_standby_names = "db_slave1" # 複数スレーブを持つ場合はカンマ区切りでDB名を追加

     

     

    マスターDBの再起動

    マスターDB側の設定は以上です。
    スレーブ側の設定もこちらでやってしまう事も可能(理由は後述)ですが、postgresql.confが分かりづらくなってしまうので、今回は都度設定していくことにします。

    この時点でPostgreSQLを再起動し、設定を反映します。

    余談ですが、PostgreSQLの起動コマンドで調べてみると、色々な起動の仕方をされている方がいますが、インストール方法の違いなどで動かない事もあるようです。
    私がいつも起動に使っているコマンドは以下のものになります。

    # initd経由
    /etc/init.d/postgresql-9.4 [start|stop|restart]
    
    # pg_ctl経由
    su postgres -c "/usr/pgsql-9.4/bin/pg_ctl [start|stop|restart] -D /var/lib/pgsql/9.4/data -m fast"

     
    どちらもrootで実行する必要がありますが、yumでインストールしたPostgreSQLで動作しました。

    pg_ctl経由の場合、$PGDATAの場所も指定できるので、PostgreSQLを2プロセス立ち上げる場合
    はpg_ctlを使う必要があります。

     

    スレーブDB側の作業

    スレーブ側の設定を進めていきます。
    スレーブDBサーバーにPostgreSQLがインストールされている前提で話を進めます。
    また、バージョンの差異もないものとして進めます。

     

    pg_basebackupでマスターをコピーする

    まず、pg_basebackupでマスターのデータ一式をコピーします。
    $PGDATAの場所をデフォルト位置と異なる場所にコピーを取る事もできますが、その場合、initd経由で起動する場合、/etc/init.d/postgresqlスクリプト内の$PGDATAのパスを変更する必要があります。
    今回は、デフォルトの/var/lib/pgsql/9.4/dataにコピーを取ることにします。
    既にある、dataディレクトリをリネームして、退避しておきます。

    マスターからデータをコピーするpg_basebackupコマンドは以下のようになります。

    pg_basebackup -h 192.168.1.1 -U repl_user -D /var/lib/pgsql/9.4/data -P --xlog

     
    DBのサイズにもよりますが、しばらく待っているとコピーが完了します。
    コピーしたdataディレクトリに入ってみると、pg_hba.confやpostgresql.confもコピーされている事に気づきますね。

    マスターDB側のpostgresql.confの編集の項で触れた、スレーブ側の設定もマスター側で可能というのは、マスター側のpostgresql.confがコピーされるからというのが理由です。
    マスターDBとして稼働するDBはスレーブDBとして稼働するために必要な設定項目を読み飛ばし、スレーブDBとして稼働するDBは、マスターDBとして稼働するために必要な設定項目を読み飛ばすので、うまくできているなと思います。

     

    postgresql.confの編集(スレーブ側)

    postgresql.confにスレーブ用の設定を行います。

     

    hot_standby

    PostgreSQLをホットスタンバイモードで稼働させるための設定項目です。
    ホットスタンバイモードで稼働しているサーバーは、更新系の処理が一切できなくなり、読み取り専用のDBになります。

    ただ、この項目単独でレプリケーションが成立する訳ではなく、hot_standbyがonかつ、この後作成するrecovery.confが存在するというのが同時に満たされた場合にレプリケーション機能が有効になります。

    hot_standby = on

     

     

    recovery.confの作成

    このファイルは一から作る必要はなく、サンプルが存在するので、それをコピーしてきて手直しします。
    recovery.confのサンプルは、/usr/pgsql-9.4/share 以下にありますので、/var/lib/pgsql/9.4/data にコピーします。

    cp /usr/pgsql-9.4/share/recovery.conf.sample /var/lib/pgsql/9.4/data/recovery.conf

     

     

    recovery.confの編集

    recovery.conf内で編集する箇所は2箇所です。
    これが終わったらレプリケーションに関する設定は完了です!

     

    standby_mode

    standby_modeをonにする事で、最後のwalファイルを受け取って処理が完了しても、次のwalファイル待ちの状態で稼働し続けます。

    standby_mode = on

     

    primary_conninfo

    マスターDBへ接続するための情報を記載します。
    特に注意する点は、application_nameの部分がマスターDBのpostgresql.confのsynchronous_standby_namesに列挙された名前に含まれているかという点です。

    これ以外は、読んだままという感じです。

    primary_conninfo = 'host=192.168.1.1 port=5432 user=repl_user password=[パスワード] application_name=db_slave1'

     

     

    スレーブDBの再起動からレプリケーションの確認まで

    以上の設定が終わったら、準備ができましたのでスレーブDBを再起動します。
    再起動のコマンドは、マスターDBと同様です。

    再起動が完了したら、レプリケーションが行われている状況になっているはずなので、マスターDB側からレプリケーションの進捗状況を確認します。

    マスターDBにログインし、以下のクエリを実行します。

    select * from pg_stat_replication;
    -[ RECORD 1 ]----+------------------------------
    pid              | 12345
    usesysid         | 12345
    usename          | repl_user
    application_name | db_slave1
    client_addr      | 192.168.1.2
    client_hostname  |
    client_port      | 43210
    backend_start    | 2016-06-12 17:01:07.923879+09
    backend_xmin     |
    state            | streaming
    sent_location    | 27/B4EED5F8
    write_location   | 27/B4EED5F8
    flush_location   | 27/B4EED5F8
    replay_location  | 27/B4EED5C0
    sync_priority    | 0
    sync_state       | async

     
    stateの項目がstreamingになっていれば、ひとまずレプリケーションは実行されているという事になります。

    どこまでデータの同期が取れているかは、sent_location、 write_location、 flush_location、 replay_locationで状況がわかります。

    • sent_locationは、マスターDBからスレーブDBへどこまでWALファイルが送信されたかを表すアドレスです。
    • write_locationは、スレーブ側のバッファ領域にどこまで書き込んだかを表すアドレスです。
    • flush_locationは、スレーブ側のディスク領域にどこまで書き込んだかを表すアドレスです。
    • replay_locationはスレーブDBでどこまでデータの取り込みが終わったかを表すアドレスです。

    4つのアドレスはデータと共に増加していくので、進み具合は一目瞭然となります。

    上記の例では、sent_location、 write_location、 flush_locationまでのアドレスは同じなので、ここまでは最新の状態になっている事を表します。
    replay_locationが若干遅れていますが、現在は非同期モードでの実行になるので、大幅にずれていなければ気にはならないところです。

     
    以上です。


    お問い合わせ 採用情報 エンジニアブログ
    ISO27001認証
    Contact PageTop
    株式会社ビヨンド

    © beyond Co., Ltd. All rights reserved.