第4回「レプリケーション改善」
第3回では、レプリケーションの新しい機能であるロジカルレプリケーションについて解説をしました。本記事では、PostgreSQL 10で導入された以下の3つのレプリケーション機能の改善について解説します。
- クォーラムコミット(Quorum Commit)機能
- レプリケーション遅延時間のレポート
- レプリケーション関連のデフォルト値の変更
クォーラムコミット(Quorum Commit)機能
PostgreSQL 10から導入されたクォーラムコミット機能について説明します。
2種類のレプリケーション同期モード
PostgreSQLのレプリケーションでは、1つのマスターサーバーは複数のスタンバイサーバーを持つことができ、それぞれ同期モード、非同期モードの2種類のモードが選べます。各モードには次のような特徴があります。
同期モード
- マスターサーバー(送信側サーバー)で発生した変更がスタンバイサーバー(受信側サーバー)へ到達し、永続化されるまでマスターでのCOMMIT処理を待つモード
- COMMITが成功するとマスターサーバーとスタンバイサーバーの両方でデータが永続化されていることが保証されるため、データの信頼性が向上する一方、スタンバイでの処理を待つため、レスポンス時間が長くなる
非同期モード
- スタンバイサーバーからの応答を待たずにCOMMITを完了するモード
- 同期モードに比べてデータの信頼性は下がるが、レスポンス時間はレプリケーションを利用しない場合と同等程度と短い
クォーラムコミット機能とは
PostgreSQLではバージョン9.6から、複数のスタンバイサーバーに対して同期モードを使用したレプリケーションが可能です。データの高い信頼性を得ることができる一方、マスターサーバーでのCOMMIT処理は、同期モードを使用している全てのスタンバイサーバーからの返答を待つ必要があるため、1つのスタンバイサーバーの遅延がトランザクション処理時間に直に影響してしまいます(図中左の方式)。その欠点を補うために開発された機能が、クォーラムコミット機能です。
クォーラムコミット機能では、全てのスタンバイサーバーからの返答を待つのではなく、その名の通り、定足数(Quorum)のスタンバイサーバーのみ待ちます。例えば、3台の内どれか2台からの返答があったらCOMMIT完了とみなす、という機能です(図中下の方式)。
設定方法と確認方法
同期レプリケーションの設定は、synchronous_standby_namesパラメーターにて行います。
synchronous_standby_names = 'ANY 2 (server1, server2, server3)'
synchronous_standby_namesパラメータに「ANY N (...)」と指定することで、クォーラムコミットが利用できます。上記の設定は、「server1, server2, server3の内、どれか二台からの応答を待つ」という意味の設定になります。一方、「FIRST N (...)」と指定すると、「括弧内のサーバーの内、左から1~N番目のサーバー全てからの応答を待つ」という意味の設定になります。
クォーラムコミットの対象となっているサーバーであるかどうかは、pg_stat_repilcationシステムビューのsync_status列で確認することができ、定足数NはSHOWコマンドで確認することが可能です。
=# SHOW synchronous_standby_names; synchronous_standby_names ---------------------------- ANY 2(server1, server2, server3) (1 row) =# SELECT application_name, sync_state FROM pg_stat_replication; application_name | sync_state ------------------+------------ node1 | quorum node2 | quorum node3 | quorum (3 rows)
sync_status列がquorumになっているサーバーは、クォーラムコミットが有効になっているサーバーです。上記の例では、3台のスタンバイサーバー(node1, node2, node3)からどれか2台からの応答を待ちます。
レプリケーション遅延時間のレポート
PostgreSQLのレプリケーションは、マスターサーバーで発生した変更をスタンバイサーバーに送信し、それをスタンバイサーバーで適用することで実現しています。そのため、非同期レプリケーションでは、スタンバイサーバーでの適用処理がマスターサーバーで発生した変更よりも遅れてしまうことは避けられません。レプリケーション遅延は、何らかの理由*1でその「遅れ」が大きくなる問題です。レプリケーション遅延が大きいと、マスターサーバーとスタンバイサーバーのデータは大きくズレるため、スタンバイサーバーでのクエリ処理結果は古い結果である可能性があります。
- *1: マスターサーバー、スタンバイサーバー間のネットワーク遅延、スタンバイサーバーの数が多すぎるなど様々な要因が考えられます
レプリケーション状況の確認には、pg_stat_replicationシステムビューが活用できますが、レプリケーション遅延の状況はバイト単位でのみ監視が可能でした。バイト単位での監視は、遅延状況を大まかに知る用途では役に立ちますが、例えば、「スタンバイサーバーでクエリを実行すると、どれくらい古いデータが見えるのか」を知りたい場合には役に立ちません。
PostgreSQL 11ではレプリケーション遅延を時間単位で報告する機能が導入されています。pg_stat_replicationシステムビューのwrite_lag列, flush_lag列, replay_lag列で確認できます。スタンバイサーバーでは、replay処理が完了した時点で、ユーザーは変更されたデータを見ることができます。そのため、「どれくらい古いデータが見えるのか」を確認するためには、replay_lag列に注目してください。
レプリケーション遅延時間の例を以下に示します。以下の例では、1台のスタンバイサーバー(server2)にて約20秒のレプリケーション遅延が発生していることがわかります。この時点で、server2へ参照クエリを実行すると20秒前のデータに対するクエリ結果が返ります。
=# SELECT application_name, write_lag, flush_lag, replay_lag FROM pg_stat_replication ; application_name | write_lag | flush_lag | replay_lag ------------------+-----------------+-----------------+----------------- server1 | 00:00:00.022447 | 00:00:00.029091 | 00:00:00.68424 server2 | 00:00:00.003227 | 00:00:00.004059 | 00:00:20.148379 server3 | 00:00:00.020398 | 00:00:00.023971 | 00:00:00.614862 (3 rows)
レプリケーション関連のデフォルト値の変更
PostgreSQL 10ではいくつかのレプリケーション関連設定値のデフォルト値が変更されました。具体的には、以下の設定値が変更されています。
- wal_levelがminimalからreplicaに変更
- max_wal_sendersが0から10に変更
- max_replication_slotsが0から10に変更
- ローカルホストからのレプリケーション接続を許可
まとめ
今回はレプリケーション関連の機能改善について解説しました。レプリケーション機能はPostgreSQLに導入されてから約8年経った今も改善が続けられています。私はクォーラムコミット機能の開発を行い、レプリケーション機能の改善に貢献することができました。これからもレプリケーション機能の発展に貢献していきたいと考えています。今回紹介した機能以外にも改善されている点があるので、興味がある方はぜひリリースノートを見てみてください。
(澤田 雅彦)
Tweet