PostgreSQL 13 ストリーミングレプリケーションの多段構成

スポンサーリンク

PostgreSQLはストリーミングレプリケーションと呼ばれるデータコピーの仕組みがあります。このページではカースケイド構成(多段構成)のレプリケーションの設定例を紹介します。

動作確認構成

以下の環境で動作確認を行います。

+------------------+     +------------------+
| 192.168.56.10/24 |---->| 192.168.56.11/24 |
|    centos10      |     |    centos11      |
|    (primary)     |  +--|   (secondary)    |
+------------------+  |  +------------------+
                      |
                      |  +------------------+
                      +->| 192.168.56.12/24 |
                         |    centos12      |
                         |   (secondary)    |
                         +------------------+

構築例

マスターサーバの構築

postgresql.confおよびpg_hba.confに以下を加筆します。

cat << EOF >> /var/lib/pgsql/13/data/postgresql.conf 

listen_addresses = '0.0.0.0'
max_wal_senders = 10
synchronous_commit = 'remote_write'
synchronous_standby_names = 'centos11'
EOF

cat << EOF >> /var/lib/pgsql/13/data/pg_hba.conf

host    replication     postgres        192.168.56.0/24  trust
EOF

再起動し設定を反映させます。

systemctl restart postgresql-13.service 

スタンバイサーバ1台目の構築

pg_basebackupコマンドを使用して、プライマリサーバのデータを1台目スタンバイサーバへコピーします。

pg_basebackup -R -D ${PGDATA} -h 192.168.56.10

postgresql.auto.confのsynchronous_standby_namesにapplication_nameを加筆します。

# vi /var/lib/pgsql/13/data/postgresql.auto.conf 

primary_conninfo = 'user=postgres <omitted> application_name=centos11'

postgresql.confをスタンバイ1台目から2台目へレプリケーションできるような設定に変更します。

具体的にはsynchronous_standby_namesをcentos11からcentos12へ変更します。

MySQLでは多段レプリケーションを実現するには–log-slave-updatesという明示的な設定が必要でしたが、PostgreSQLでは明示設定なしに多段レプリケーションを実現する事ができます。

# vi /var/lib/pgsql/13/data/postgresql.conf

listen_addresses = '0.0.0.0'
max_wal_senders = 10
synchronous_commit = 'remote_write'
synchronous_standby_names = 'centos12'

postgresqlを起動します。

systemctl start postgresql-13.service

レプリケーションが開始された旨のログを確認します。

[root@centos11 ~]# tail -n 3 /var/lib/pgsql/13/data/log/postgresql-Sun.log 
2020-12-27 19:41:25.355 JST [1131] LOG:  0/2000100 でリカバリの一貫性が確保されました
2020-12-27 19:41:25.355 JST [1128] LOG:  データベースシステムはリードオンリー接続の受け付け準備ができました
2020-12-27 19:41:25.459 JST [1135] LOG:  プライマリのタイムライン1の 0/3000000からでWALストリーミングを始めます

スタンバイサーバ2台目の構築

pg_basebackupコマンドを使用して、スタンバイサーバ1台目のデータをスタンバイサーバ2台目へコピーします。

pg_basebackup -R -D ${PGDATA} -h 192.168.56.11

postgresql.auto.confのsynchronous_standby_namesにapplication_nameを加筆します。また、スタンバイサーバ1台目から引き継いだprimary_conninfoの設定を削除またはコメントアウトします。

# vi /var/lib/pgsql/13/data/postgresql.auto.conf 

# primary_conninfo = <omitted>
primary_conninfo = 'user=postgres <omitted> application_name=centos12'

postgresql.confについてスタンバイサーバ1台目から引き継いだ設定をコメントアウトします。

# vi /var/lib/pgsql/13/data/postgresql.conf

#listen_addresses = '0.0.0.0'
#max_wal_senders = 10
#synchronous_commit = 'remote_write'
#synchronous_standby_names = 'centos12'

postgresqlを起動します。

systemctl start postgresql-13.service

レプリケーションが開始された旨のログを確認します。

[root@centos12 ~]# tail -n 3 /var/lib/pgsql/13/data/log/postgresql-Sun.log 
2020-12-27 19:57:58.406 JST [1127] LOG:  0/3000148のレコード長が不正です:長さは24である必要がありますが、実際は0でした
2020-12-27 19:57:58.406 JST [1124] LOG:  データベースシステムはリードオンリー接続の受け付け準備ができました
2020-12-27 19:57:58.570 JST [1131] LOG:  プライマリのタイムライン1の 0/3000000からでWALストリーミングを始めます

プライマリサーバに何らかのデータを書き込みます。

[postgres@centos10 ~]$ psql -c "CREATE DATABASE test"
CREATE DATABASE
[postgres@centos10 ~]$ 

2台目のスタンバイサーバまでレプリケーションされている事を確認します。

[postgres@centos12 ~]$ psql -l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-----------+----------+----------+-------------+-------------+-----------------------
 postgres  | postgres | UTF8     | ja_JP.UTF-8 | ja_JP.UTF-8 | 
 template0 | postgres | UTF8     | ja_JP.UTF-8 | ja_JP.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | ja_JP.UTF-8 | ja_JP.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 test      | postgres | UTF8     | ja_JP.UTF-8 | ja_JP.UTF-8 | 
(4 rows)

障害復旧例

プライマリサーバへの昇格

centos10に障害が発生し、centos11がスタンバイからプライマリへ昇格するシナリオを想定して動作確認を行います。

+------------------+     +------------------+
| 192.168.56.10/24 |---->| 192.168.56.11/24 |
|    centos10      |     |    centos11      |
|  (out of order)  |  +--|    (primary)     |
+------------------+  |  +------------------+
                      |
                      |  +------------------+
                      +->| 192.168.56.12/24 |
                         |    centos12      |
                         |   (secondary)    |
                         +------------------+

pg_ctl promoteコマンドを使用してスタンバイからプライマリへ昇格させます。

[postgres@centos11 ~]$ /usr/pgsql-13/bin/pg_ctl promote
waiting for server to promote.... done
server promoted
[postgres@centos11 ~]$

この時、タイムラインが1から2になった事に留意ください。

[postgres@centos11 ~]$ tail -n 20 /var/lib/pgsql/13/data/log/postgresql-Sun.log  
2020-12-27 19:41:25.355 JST [1128] LOG:  データベースシステムはリードオンリー接続の受け付け準備ができました
2020-12-27 19:41:25.459 JST [1135] LOG:  プライマリのタイムライン1の 0/3000000からでWALストリーミングを始めます
2020-12-27 20:00:52.227 JST [1131] LOG:  昇格要求を受信しました
2020-12-27 20:00:52.227 JST [1135] FATAL:  管理者コマンドにより WAL 受信プロセスを終了しています
2020-12-27 20:00:52.229 JST [1131] LOG:  0/30009C8のレコード長が不正です:長さは24である必要がありますが、実際は0でした
2020-12-27 20:00:52.229 JST [1131] LOG:  REDOが0/3000990で終了しました
2020-12-27 20:00:52.229 JST [1131] LOG:  最後に完了したトランザクションのログ時刻は2020-12-27 19:58:48.115269+09でした
2020-12-27 20:00:52.230 JST [1131] LOG:  新しいタイムラインIDを選択: 2
2020-12-27 20:00:52.287 JST [1131] LOG:  アーカイブリカバリが完了しました
2020-12-27 20:00:52.316 JST [1128] LOG:  データベースシステムの接続受け付け準備が整いました

この状態で更新処理を試みると、更新処理がスタンバイに反映されてない可能性を示すメッセージが表示されます。

これはスタンバイ(centos12)のタイムラインが1のままだからです。

[postgres@centos11 ~]$ psql -c "CREATE DATABASE test2"
^CCancel request sent
WARNING:  ユーザからの要求により同期レプリケーションの待ち状態をキャンセルしています
DETAIL:  トランザクションはローカルではすでにコミット済みですが、スタンバイ側にはレプリケーションされていない可能性があります。
CREATE DATABASE
[postgres@centos11 ~]$

スタンバイサーバのタイムライン変更

スタンバイサーバのrecovery_target_timelineの設定を確認します。デフォルト設定の場合はlatestになっていますので、再起動すれば最新のタイムラインが反映されます。

[postgres@centos12 ~]$ psql -c "SHOW ALL" | grep timeline
 recovery_target_timeline               | latest                                                                                                                                                                                                                                                         | Specifies the timeline to recover into.
[postgres@centos12 ~]$

再起動しタイムラインを最新にします。

[root@centos12 ~]# systemctl start postgresql-13.service

タイムラインが2に変わった事を確認します。

[root@centos12 ~]# tail -n 3 /var/lib/pgsql/13/data/log/postgresql-Sun.log 
2020-12-27 20:03:19.187 JST [1316] LOG:  0/30014A0のレコード長が不正です:長さは24である必要がありますが、実際は0でした
2020-12-27 20:03:19.187 JST [1313] LOG:  データベースシステムはリードオンリー接続の受け付け準備ができました
2020-12-27 20:03:19.266 JST [1320] LOG:  プライマリのタイムライン2の 0/3000000からでWALストリーミングを始めます

マスターサーバに何らかの更新処理を発生させます。

[postgres@centos11 ~]$ psql -c "CREATE DATABASE test2"
CREATE DATABASE
[postgres@centos11 ~]$ 

更新がスタンバイサーバに反映されている事を確認します。

[postgres@centos12 ~]$ psql -l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-----------+----------+----------+-------------+-------------+-----------------------
 postgres  | postgres | UTF8     | ja_JP.UTF-8 | ja_JP.UTF-8 | 
 template0 | postgres | UTF8     | ja_JP.UTF-8 | ja_JP.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | ja_JP.UTF-8 | ja_JP.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 test      | postgres | UTF8     | ja_JP.UTF-8 | ja_JP.UTF-8 | 
 test2     | postgres | UTF8     | ja_JP.UTF-8 | ja_JP.UTF-8 | 
(5 rows)
タイトルとURLをコピーしました