データベースを管理する人にとって、レプリケーションの知識は必須です。それはおそらくあなたが何度も何度も見たことがあるが、決して古くなることのないトピックです。このブログでは、PostgreSQLの組み込みレプリケーション機能の歴史を少し確認し、ストリーミングレプリケーションの仕組みについて詳しく説明します。
レプリケーションについて話すときは、WALについてたくさん話します。それでは、先行書き込みログについて少し簡単に確認しましょう。
先行書き込みログ(WAL)
先行書き込みログは、データの整合性を確保するための標準的な方法であり、デフォルトで自動的に有効になります。
WALは、PostgreSQLのREDOログです。しかし、REDOログとは正確には何ですか?
REDOログには、データベースで行われたすべての変更が含まれ、レプリケーション、リカバリ、オンラインバックアップ、およびポイントインタイムリカバリ(PITR)に使用されます。データページに適用されていない変更は、REDOログからやり直すことができます。
WALを使用すると、トランザクションによって変更されたすべてのデータファイルではなく、トランザクションがコミットされたことを保証するためにログファイルのみをディスクにフラッシュする必要があるため、ディスク書き込みの数が大幅に減少します。
WALレコードは、データに加えられた変更をビットごとに指定します。各WALレコードはWALファイルに追加されます。挿入位置はログシーケンス番号(LSN)であり、ログへのバイトオフセットであり、新しいレコードごとに増加します。
WALは、データディレクトリの下のpg_walディレクトリ(またはPostgreSQLバージョン<10の場合はpg_xlog)に保存されます。これらのファイルのデフォルトサイズは16MBです(サーバーの構築時に--with-wal-segsize設定オプションを変更することでサイズを変更できます)。これらには、「000000010000000000000000」という形式の一意の増分名があります。
pg_walに含まれるWALファイルの数は、postgresql.conf構成ファイルのパラメーターcheckpoint_segments(または、バージョンによってはmin_wal_sizeとmax_wal_size)に割り当てられた値によって異なります。
すべてのPostgreSQLインストールを構成するときに設定する必要があるパラメーターの1つは、wal_levelです。 wal_levelは、WALに書き込まれる情報の量を決定します。デフォルト値は最小で、クラッシュまたは即時シャットダウンから回復するために必要な情報のみを書き込みます。アーカイブは、WALアーカイブに必要なロギングを追加します。 hot_standbyは、スタンバイサーバーで読み取り専用クエリを実行するために必要な情報をさらに追加します。論理は、論理デコードをサポートするために必要な情報を追加します。このパラメーターは再起動が必要なため、それを忘れた場合、実行中の実稼働データベースで変更するのは難しい場合があります。
詳細については、こちらまたはこちらの公式ドキュメントを確認してください。 WALについて説明したので、PostgreSQLでのレプリケーションの履歴を確認しましょう。
PostgreSQLでのレプリケーションの歴史
PostgreSQLが実装した最初のレプリケーション方法(ウォームスタンバイ)(バージョン8.2、2006年に遡る)は、ログ配布方法に基づいていました。
これは、WALレコードが1つのデータベースサーバーから別のデータベースサーバーに直接移動されて適用されることを意味します。継続的なPITRと言えます。
PostgreSQLは、WALレコードを一度に1つのファイル(WALセグメント)に転送することにより、ファイルベースのログ配布を実装します。
このレプリケーションの実装には欠点があります。プライマリサーバーで重大な障害が発生した場合、まだ出荷されていないトランザクションが失われます。そのため、データ損失のウィンドウがあります(archive_timeoutパラメーターを使用してこれを調整できます。このパラメーターは数秒に設定できます。ただし、このような低い設定では、ファイルの転送に必要な帯域幅が大幅に増加します)。
このファイルベースのログ配布方法は、次の図で表すことができます。
PostgreSQLファイルベースのログ配布ストリーミングレプリケーションを使用すると、ファイルベースのログ配布で可能な場合よりも最新の状態を維持できます。これは、WALファイルがいっぱいになるのを待たずに、プライマリサーバーと1つまたは複数のスタンバイサーバー間でWALレコード(WALファイルはWALレコードで構成されます)をオンザフライ(レコードベースのログ配布)で転送することで機能します。
実際には、スタンバイサーバーで実行されているWALレシーバーと呼ばれるプロセスは、TCP/IP接続を使用してプライマリサーバーに接続します。プライマリサーバーには、WAL送信者という名前の別のプロセスが存在し、WALレジストリをスタンバイサーバーに送信する役割を果たします。
次の図は、ストリーミングレプリケーションを表しています。
PostgreSQLストリーミングレプリケーションストリーミングレプリケーションを構成するときに、WALアーカイブを有効にするオプションがあります。
この手順は必須ではありませんが、堅牢なレプリケーション設定にとって非常に重要です。メインサーバーがスタンバイサーバーにまだ適用されていない古いWALファイルをリサイクルしないようにする必要があります。これが発生した場合は、レプリカを最初から再作成する必要があります。
継続的なアーカイブを使用してレプリケーションを構成する場合、バックアップから開始します。プライマリとの同期状態に到達するには、バックアップ後に発生したWALでホストされているすべての変更を適用する必要があります。このプロセス中、スタンバイは最初にアーカイブの場所で使用可能なすべてのWALを復元します(restore_commandを呼び出すことによって実行されます)。 restore_commandは、最後にアーカイブされたWALレコードに到達すると失敗するため、その後、スタンバイはpg_walディレクトリを調べて、そこに変更が存在するかどうかを確認します(これにより、プライマリサーバーがクラッシュしたときのデータ損失と、すでに移動され、レプリカに適用されていますが、まだアーカイブされていません。
それが失敗し、要求されたレコードがそこに存在しない場合、ストリーミングレプリケーションを介してプライマリサーバーとの通信を開始します。
ストリーミングレプリケーションが失敗すると、手順1に戻り、アーカイブからレコードが再度復元されます。アーカイブpg_walからの再試行のこのループは、サーバーが停止するか、トリガーファイルによってフェイルオーバーがトリガーされるまで続きます。
次の図は、継続的なアーカイブを使用したストリーミングレプリケーション構成を表しています。
継続的なアーカイブを使用したPostgreSQLストリーミングレプリケーションただし、コミットとレプリカの変更の影響との間のこの遅延は、もちろん、レプリカサーバーが追いつくのに十分強力であると仮定すると、非常に小さい(数ミリ秒)と想定されます。負荷。
わずかなデータ損失のリスクさえ許容できない場合のために、バージョン9.1では同期レプリケーション機能が導入されました。
同期レプリケーションでは、書き込みトランザクションの各コミットは、コミットがプライマリサーバーとスタンバイサーバーの両方のディスクの先行書き込みログに書き込まれるという確認が受信されるまで待機します。
この方法は、データ損失の可能性を最小限に抑えます。そのためには、プライマリとスタンバイの両方が同時に失敗する必要があります。
この構成の明らかな欠点は、すべての関係者が応答するまで待機する必要があるため、各書き込みトランザクションの応答時間が長くなることです。したがって、コミットの時間は、少なくとも、プライマリとレプリカの間のラウンドトリップです。読み取り専用トランザクションはこれによる影響を受けません。
同期レプリケーションを設定するには、各スタンバイserver.confファイルのリカバリのprimary_conninfoでapplication_nameを指定する必要があります:primary_conninfo ='... aplication_name=standbyX'。
同期レプリケーションに参加するスタンバイサーバーのリストも指定する必要があります:synchronous_standby_name ='standbyX、standbyY'。
1つまたは複数の同期サーバーをセットアップできます。このパラメーターは、リストされたものから同期スタンバイを選択する方法(FIRSTおよびANY)も指定します。同期レプリケーションモードの設定の詳細については、このブログをご覧ください。 ClusterControlを介してデプロイするときに同期レプリケーションを設定することもできます。
レプリケーションを構成して稼働させたら、モニタリングを実装する必要があります
PostgreSQLレプリケーションの監視
マスターサーバーのpg_stat_replicationビューには、多くの関連情報があります。
postgres=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 756
usesysid | 16385
usename | cmon_replication
application_name | pgsql_0_node_0
client_addr | 10.10.10.137
client_hostname |
client_port | 36684
backend_start | 2022-04-13 17:45:56.517518+00
backend_xmin |
state | streaming
sent_lsn | 0/400001C0
write_lsn | 0/400001C0
flush_lsn | 0/400001C0
replay_lsn | 0/400001C0
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
reply_time | 2022-04-13 17:53:03.454864+00
-
pid:walsenderプロセスのプロセスID。
-
usesysid:ストリーミングレプリケーションに使用されるユーザーのOID。
-
usename:ストリーミングレプリケーションに使用されるユーザーの名前。
-
application_name:マスターに接続されているアプリケーション名。
-
client_addr:スタンバイ/ストリーミングレプリケーションのアドレス。
-
client_hostname:スタンバイのホスト名。
-
client_port:スタンバイがWAL送信者と通信するTCPポート番号。
-
backend_start:SRがプライマリに接続したときの開始時刻。
-
状態:現在のWAL送信者の状態、つまりストリーミング。
-
send_lsn:スタンバイに送信された最後のトランザクションの場所。
-
write_lsn:スタンバイ時にディスクに書き込まれた最後のトランザクション。
-
flush_lsn:スタンバイ時のディスクでの最後のトランザクションフラッシュ。
-
reply_lsn:スタンバイ時のディスクでの最後のトランザクションフラッシュ。
-
sync_priority:同期スタンバイとして選択されたスタンバイサーバーの優先度。
-
sync_state:スタンバイの同期状態(非同期か同期か)
送信者(プライマリノード):
[[email protected] ~]# ps aux |grep postgres
postgres 727 0.0 2.2 917060 47936 ? Ss 17:45 0:00 /usr/pgsql-14/bin/postmaster -D /var/lib/pgsql/14/data/
postgres 732 0.0 0.2 351904 5280 ? Ss 17:45 0:00 postgres: 14/main: logger
postgres 734 0.0 0.5 917188 10560 ? Ss 17:45 0:00 postgres: 14/main: checkpointer
postgres 735 0.0 0.4 917208 9908 ? Ss 17:45 0:00 postgres: 14/main: background writer
postgres 736 0.0 1.0 917060 22928 ? Ss 17:45 0:00 postgres: 14/main: walwriter
postgres 737 0.0 0.4 917748 9128 ? Ss 17:45 0:00 postgres: 14/main: autovacuum launcher
postgres 738 0.0 0.3 917060 6320 ? Ss 17:45 0:00 postgres: 14/main: archiver last was 00000001000000000000003F
postgres 739 0.0 0.2 354160 5340 ? Ss 17:45 0:00 postgres: 14/main: stats collector
postgres 740 0.0 0.3 917632 6892 ? Ss 17:45 0:00 postgres: 14/main: logical replication launcher
postgres 756 0.0 0.6 918252 13124 ? Ss 17:45 0:00 postgres: 14/main: walsender cmon_replication 10.10.10.137(36684) streaming 0/400001C0
受信者(スタンバイノード):
[[email protected] ~]# ps aux |grep postgres
postgres 727 0.0 2.2 917060 47576 ? Ss 17:45 0:00 /usr/pgsql-14/bin/postmaster -D /var/lib/pgsql/14/data/
postgres 732 0.0 0.2 351904 5396 ? Ss 17:45 0:00 postgres: 14/main: logger
postgres 733 0.0 0.3 917196 6360 ? Ss 17:45 0:00 postgres: 14/main: startup recovering 000000010000000000000040
postgres 734 0.0 0.4 917060 10056 ? Ss 17:45 0:00 postgres: 14/main: checkpointer
postgres 735 0.0 0.3 917060 6304 ? Ss 17:45 0:00 postgres: 14/main: background writer
postgres 736 0.0 0.2 354160 5456 ? Ss 17:45 0:00 postgres: 14/main: stats collector
postgres 737 0.0 0.6 924532 12948 ? Ss 17:45 0:00 postgres: 14/main: walreceiver streaming 0/400001C0
レプリケーションがどの程度最新であるかを確認する1つの方法は、プライマリサーバーで生成されたがスタンバイサーバーではまだ適用されていないWALレコードの量を確認することです。
プライマリ:
postgres=# SELECT pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
0/400001C0
(1 row)
スタンバイ:
postgres=# SELECT pg_last_wal_receive_lsn();
pg_last_wal_receive_lsn
-------------------------
0/400001C0
(1 row)
postgres=# SELECT pg_last_wal_replay_lsn();
pg_last_wal_replay_lsn
------------------------
0/400001C0
(1 row)
スタンバイノードで次のクエリを使用して、秒単位でラグを取得できます。
postgres=# SELECT CASE WHEN pg_last_wal_receive_lsn() = pg_last_wal_replay_lsn()
THEN 0
ELSE EXTRACT (EPOCH FROM now() - pg_last_xact_replay_timestamp())
END AS log_delay;
log_delay
-----------
0
(1 row)
また、最後に受信したメッセージを確認することもできます:
postgres=# SELECT status, last_msg_receipt_time FROM pg_stat_wal_receiver;
status | last_msg_receipt_time
-----------+------------------------------
streaming | 2022-04-13 18:32:39.83118+00
(1 row)
ClusterControlを使用したPostgreSQLレプリケーションの監視
PostgreSQLクラスターを監視するには、ClusterControlを使用して、展開、バックアップ、スケールアウトなどのいくつかの追加の管理タスクを監視および実行できます。
概要セクションには、データベースクラスターの全体像が表示されます。現在のステータス。詳細を確認するには、ダッシュボードセクションにアクセスしてください。ダッシュボードセクションには、さまざまなグラフに分けられた多くの役立つ情報が表示されます。
トポロジセクションでは、ユーザーの現在のトポロジを確認できます-使いやすい方法であり、[ノードアクション]ボタンを使用して、ノード上でさまざまなタスクを実行することもできます。
ストリーミングレプリケーションは、WALレコードを送信してスタンバイに適用することに基づいていますサーバーでは、どのファイルにどのバイトを追加または変更するかを指示します。その結果、スタンバイサーバーは実際にはプライマリサーバーのビットごとのコピーになります。ただし、ここにはいくつかのよく知られた制限があります:
-
別のバージョンまたはアーキテクチャに複製することはできません。
-
スタンバイサーバーでは何も変更できません。
-
複製する内容の粒度はあまりありません。
したがって、これらの制限を克服するために、PostgreSQL10は論理レプリケーションのサポートを追加しました
論理レプリケーション
論理レプリケーションもWALファイルの情報を使用しますが、論理変更にデコードします。どのバイトが変更されたかを知る代わりに、どのデータがどのテーブルに挿入されたかを正確に知ることができます。
これは、「パブリッシュ」および「サブスクライブ」モデルに基づいており、1人以上のサブスクライバーが次のようなパブリッシャーノード上の1つ以上のパブリケーションをサブスクライブします。
PostgreSQL論理レプリケーション
ストリーミングレプリケーションを使用すると、WALレコードを継続的に送信してスタンバイサーバーに適用できるため、プライマリサーバーで更新された情報がスタンバイサーバーにリアルタイムで転送され、両方の同期が維持されます。 。
ClusterControlを使用すると、ストリーミングレプリケーションの設定が簡単になり、30日間無料で評価できます。
PostgreSQLでの論理レプリケーションについて詳しく知りたい場合は、論理レプリケーションの概要とPostgreSQLレプリケーションのベストプラクティスに関するこの投稿を確認してください。
オープンソースベースのデータベースを管理するためのその他のヒントとベストプラクティスについては、TwitterとLinkedInでフォローし、ニュースレターを購読して定期的に更新してください。