このページでは、Cloud SQL リードレプリカのレプリケーション ラグのトラブルシューティングと修正方法について説明します。
概要
Cloud SQL リードレプリカは、PostgreSQL ストリーミング レプリケーションを使用します。変更は、プライマリ インスタンスの先行書き込みログ(WAL)に書き込まれます。WAL sender がレプリカの WAL receiver に WAL を送信し、そこで適用されます。レプリケーション ラグは、次のようないくつかのシナリオで発生する可能性があります。
- プライマリ インスタンスが、レプリカに変更を十分な速さで送信できない。
- レプリカが変更を十分な速さで受信できない。
- レプリカが変更を十分な速さで適用できない。
network_lag 指標でモニタリングできます。3 つめは replica_lag 指標を介してモニタリングされます。replica_lag が高い場合、レプリカがレプリケーションの変更を十分な速さで適用できないことを意味します。合計ラグは、replica_byte_lag 指標を介してモニタリングできます。この指標には詳細を示すラベルがあります。これらの指標については、以下のレプリケーション ラグのモニタリングのセクションで説明します。レプリカが適切にプロビジョニングされていることを確認する
プライマリ インスタンスよりも小さいレプリカ インスタンス(vCPU とメモリが少ないなど)では、レプリケーションの遅延が発生する可能性があります。小さいレプリカでは、大きいプライマリ インスタンスとは異なるデフォルトの構成フラグが設定されている場合もあります。レプリケーションの負荷を処理するのに十分なリソースを確保するため、レプリカ インスタンスはプライマリ インスタンスと同じサイズか、それ以上にすることをおすすめします。
レプリカの CPU 使用率が高いと、レプリケーションが遅延する可能性もあります。レプリカの CPU 使用率が高い場合(90% を超えるなど)、レプリカの CPU 容量を増やすことを検討してください。
SHOW ALL コマンドを使用すると、レプリカ インスタンスとプライマリ インスタンスの構成を表示して、違いを比較できます。クエリとスキーマを最適化する
このセクションでは、レプリケーションのパフォーマンスを改善するためによく実行するクエリとスキーマの最適化について説明します。
リードレプリカでの長時間実行クエリ
レプリカで長時間実行されるクエリが原因で、Cloud SQL のレプリケーションがブロックされる場合があります。これは、レプリケーションがレプリカのクエリで読み取られている行に変更(VACUUM オペレーションなど)を適用しようとしている場合に発生することがあります。
オンライン トランザクション処理(OLTP)とオンライン分析処理(OLAP)に別々のレプリカを使用し、長時間実行クエリのみを OLAP レプリカに送信できます。
長時間実行されるトランザクションによって発生するレプリケーションの遅延やブロックを解決するには、次のことをおすすめします。
-
スタンバイ遅延フラグを調整します。
max_standby_archive_delayフラグとmax_standby_streaming_delayフラグは、レプリカがレプリケーションと競合するスタンバイ クエリをキャンセルするまでの待機時間を制御します。妥当な値は 30 ~ 60 秒程度です。pg_stat_database_conflictsビューで、クエリの競合に関する分析情報を確認できます。 -
hot_standby_feedbackフラグを有効にします。レプリカでhot_standby_feedbackフラグをonに設定すると、プライマリでのバキューム オペレーションを遅延させることができます。ただし、これによりプライマリでテーブルの肥大化が発生する可能性があるため、トレードオフとなります。
詳細については、PostgreSQL のドキュメントをご覧ください。
ネットワークの遅延が大きい
ネットワーク ラグが高い場合は、プライマリが WAL レコードを送信していないか、レプリカが WAL レコードを十分に高速で受信していないことを示します。この問題は、次の原因で発生する可能性があります。
- クロスリージョン レプリケーション。異なるリージョン間でレプリケートすると、ネットワーク レイテンシが高くなる可能性があります。
- プライマリ CPU 使用率が高い。プライマリの CPU が 90% を超えている場合、WAL 送信者プロセスに十分な CPU 時間が割り当てられないことがあります。プライマリの負荷を減らすか、CPU を増やすことを検討してください。
- レプリカの CPU 使用率が高い。レプリカの CPU が 90% を超えると、WAL receiver プロセスに十分な CPU 時間が割り当てられない可能性があります。レプリカの負荷を軽減するか、CPU を増やすことを検討してください。
- ネットワーク帯域幅の問題またはディスク I/O のボトルネック。より近いリージョンまたはスループットの高いディスク構成を使用すると、この問題を解決できる可能性があります。リージョン間のトラフィックを削減するために、プライマリ インスタンスの
wal_compressionフラグの値を変更することを検討してください。
cloudsql.googleapis.com/database/replication/network_lag 指標を使用して、ネットワーク ラグをモニタリングできます。実際の遅延がそれよりも長くても、この指標の上限は 25 秒です。
この network_lag 指標は、replica_lag_type ラベルで示されるバイト単位の sent_location ラグを測定する cloudsql.googleapis.com/database/postgresql/replication/replica_byte_lag 指標に似ています。
DDL による排他ロック
データ定義言語(DDL)コマンド(ALTER TABLE や CREATE INDEX など)では、排他的ロックによってレプリカでレプリケーション ラグが発生することがあります。ロックの競合を回避するには、レプリカでクエリの負荷が低いときに DDL の実行をスケジュールすることを検討してください。
レプリカの過負荷
リードレプリカが受信するクエリが多すぎると、レプリケーションがブロックされることがあります。読み取りを複数のレプリカに分割して、各レプリカの負荷を減らすことを検討してください。
クエリの急増を回避するには、アプリケーション ロジックまたはプロキシレイヤ(1 つ使用している場合)でレプリカの読み取りクエリを抑制することを検討してください。
プライマリ インスタンスでアクティビティが急増した場合は、更新を分散させることを検討してください。
モノリシックなプライマリ データベース
プライマリ データベースを垂直方向(または水平方向)に分割して、1 つ以上のラグテーブルが他のすべてのテーブルを抑制しないようにすることを検討してください。
レプリケーション ラグをモニタリングする
replica_lag 指標と network_lag 指標を使用してレプリケーション ラグをモニタリングし、ラグの原因がプライマリ データベース、ネットワーク、レプリカのどれにあるのかを識別できます。
| 指標 | 説明 |
|---|---|
| レプリケーション ラグ ( cloudsql.googleapis.com) |
レプリカの状態がプライマリ インスタンスの状態よりも遅れている秒数。これは、現在の時刻と、現在レプリカに適用されているトランザクションをプライマリ データベースが commit した時点のタイムスタンプとの差です。特に、レプリカが書き込みを受信していても、レプリカがデータベースへの書き込みをまだ適用していない場合、書き込みは遅延として記録される可能性があります。 この指標は、レプリカの |
| ラグバイト ( cloudsql.googleapis.com) |
プライマリ データベースの状態からのレプリカの状態の遅れ(バイト数)。
|
| ネットワーク ラグ ( cloudsql.googleapis.com) |
プライマリ データベースの commit からレプリカの WAL receiver に到達するまでにかかる時間(秒)。
|
レプリケーションを検証する
レプリケーションが機能していることを確認するには、レプリカに対して次のステートメントを実行します。 select status, last_msg_receipt_time from pg_stat_wal_receiver;
レプリケーションが行われている場合は、ステータス streaming と最近の last_msg_receipt_time が表示されます。
postgres=> select status, last_msg_receipt_time from pg_stat_wal_receiver;
status | last_msg_receipt_time
-----------+-------------------------------
streaming | 2020-01-21 20:19:51.461535+00
(1 row)
レプリケーションが行われていない場合、空の結果が返されます。
postgres=> select status, last_msg_receipt_time from pg_stat_wal_receiver;
status | last_msg_receipt_time
--------+-----------------------
(0 rows)