PostgreSQLのディザスターリカバリーに遅延レプリケーションを使用した方法







レプリケーションはバックアップではありません。 かどうか? これは、誤ってショートカットを削除することにより、回復のために遅延複製を使用した方法です。







GitLabのインフラストラクチャスペシャリストは 、GitLabの最大のインスタンスであるGitLab.comを実行する責任があります。 300万人のユーザーとほぼ700万のプロジェクトがあり、これは専用アーキテクチャーを備えた最大のオープンソースSaaSサイトの1つです。 PostgreSQLデータベースシステムがなければ、GitLab.comインフラストラクチャは遠ざかりません。データが失われる可能性のある障害が発生した場合、フォールトトレランスのためにそれを行うことはありません。 このような大惨事が発生することはまずありませんが、さまざまなバックアップおよびレプリケーションメカニズムを用意し、十分に準備を整えています。







レプリケーションは、データベースバックアップツールではありません( 以下を参照 )。 しかし、遅延レプリケーションを使用して誤って削除されたデータをすばやく回復する方法を確認します。GitLab.comで、ユーザーはgitlab-ce



プロジェクトのショートカット削除し、マージリクエストとタスクとの接続を失いました。







遅延レプリカを使用すると、わずか1.5時間でデータを回復できました。 それがどうであったかを見てください。







PostgreSQLを使用したポイントインタイムリカバリ



PostgreSQLには、特定の時点でデータベースの状態を復元する組み込み関数があります。 Point-in-Time Recovery (PITR)と呼ばれ、レプリカの関連性を維持する同じメカニズムを使用します:データベースクラスター全体の信頼性の高いスナップショット(基本バックアップ)から開始し、特定の時点まで多数の状態変更を適用します。







この機能をコールドバックアップに使用するために、基本的なデータベースバックアップを定期的に作成し、アーカイブに保存します(GitLabアーカイブはGoogleクラウドストレージに存在します )。 また、 先行書き込みログ (WAL) ログをアーカイブすることにより、データベースの状態の変化を監視します。 そして、これらすべてを使用して、災害復旧のためにPITRを実行できます。エラーの前に撮影した写真から始め、障害が発生するまでWALアーカイブから変更を適用します。







遅延複製とは何ですか?



遅延複製は、遅延したWAL変更の適用です。 つまり、トランザクションはX



時間に発生しましたが、レプリカにはX + d



時間X + d



時間にd



遅延で表示されます。







PostgreSQLには、データベースの物理レプリカを構成する2つの方法があります。アーカイブからの復元とストリーミングレプリケーションです。 アーカイブからの復元は、実際にはPITRのように機能しますが、継続的に:WALアーカイブから絶えず変更を抽出し、レプリカに適用します。 また、 ストリーミングレプリケーションは、アップストリームデータベースホストからWALストリームを直接取得します。 アーカイブからの回復をお勧めします。管理が簡単で、通常のパフォーマンスが得られます。これは、作業中のクラスターに遅れることはありません。







アーカイブからの遅延リカバリを設定する方法



回復オプションはrecovery.conf



ファイルで説明されています。 例:







 standby_mode = 'on' restore_command = '/usr/bin/envdir /etc/wal-ed/env /opt/wal-e/bin/wal-e wal-fetch -p 4 "%f" "%p"' recovery_min_apply_delay = '8h' recovery_target_timeline = 'latest'
      
      





これらのパラメーターを使用して、アーカイブからの回復を備えた遅延レプリカを設定します。 ここで、 wal-eはアーカイブからWALセグメント( restore_command



)を抽出するために使用され、変更は8時間後に適用されます( recovery_min_apply_delay



)。 レプリカは、たとえばクラスターのフェイルオーバー( recovery_target_timeline



)によるアーカイブのタイムラインの変更を監視します。







recovery_min_apply_delay



を使用すると、遅延ストリーミングレプリケーションを構成できますが、レプリケーションスロット、ホットスペアフィードバックなどに関連するいくつかのトリックがあります。 WALアーカイブにより、それらを回避できます。







recovery_min_apply_delay



パラメーターは、PostgreSQL 9.3でのみ登場しました。 以前のバージョンでは、遅延レプリケーションの場合、リカバリ管理機能pg_xlog_replay_pause(), pg_xlog_replay_resume()



)の組み合わせを構成するか、時間遅延のためにアーカイブにWALセグメントを保持する必要があります。







PostgreSQLはどのようにこれを行いますか?



PostgreSQLが遅延回復を実装する方法を知りたい。 recoveryApplyDelay(XlogReaderState)



見てみましょう。 WALの各エントリのメインループから呼び出されます。







 static bool recoveryApplyDelay(XLogReaderState *record) { uint8 xact_info; TimestampTz xtime; long secs; int microsecs; /* nothing to do if no delay configured */ if (recovery_min_apply_delay <= 0) return false; /* no delay is applied on a database not yet consistent */ if (!reachedConsistency) return false; /* * Is it a COMMIT record? * * We deliberately choose not to delay aborts since they have no effect on * MVCC. We already allow replay of records that don't have a timestamp, * so there is already opportunity for issues caused by early conflicts on * standbys. */ if (XLogRecGetRmid(record) != RM_XACT_ID) return false; xact_info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK; if (xact_info != XLOG_XACT_COMMIT && xact_info != XLOG_XACT_COMMIT_PREPARED) return false; if (!getRecordTimestamp(record, &xtime)) return false; recoveryDelayUntilTime = TimestampTzPlusMilliseconds(xtime, recovery_min_apply_delay); /* * Exit without arming the latch if it's already past time to apply this * record */ TimestampDifference(GetCurrentTimestamp(), recoveryDelayUntilTime, &secs, &microsecs); if (secs <= 0 && microsecs <= 0) return false; while (true) { // Shortened: // Use WaitLatch until we reached recoveryDelayUntilTime // and then break; } return true; }
      
      





一番下の行は、遅延がトランザクションコミットタイムスタンプ( xtime



)に記録された物理時間に基づいていることです。 ご覧のとおり、遅延はコミットにのみ適用され、他のレコードには影響しません。すべての変更は直接適用され、コミットは遅延されるため、遅延が設定された後にのみ変更が表示されます。







レイジーレプリカを使用してデータを回復する方法



実稼働環境にデータベースクラスターがあり、8時間遅れのレプリカがあるとします。 誤ってショートカットを削除する例を使用して、データを回復する方法を見てみましょう。







問題を発見したとき、レイジーレプリカのアーカイブからの回復一時停止しました。







 SELECT pg_xlog_replay_pause();
      
      





一時停止では、レプリカがDELETE



要求を繰り返すリスクはありませんでした。 あなたがそれを理解する時間が必要な場合に便利なもの。







一番下の行は、遅延レプリカがDELETE



要求の前にポイントに到達する必要があるということです。 削除の物理的な時間はほぼわかっていました。 recovery_min_apply_delay



を削除し、 recovery_min_apply_delay



に追加しました。 そのため、レプリカは遅延なく適切な瞬間に到達します。







 recovery_target_time = '2018-10-12 09:25:00+00'
      
      





タイムスタンプでは、見逃さないように超過分を減らすことをお勧めします。 確かに、減少が大きいほど、より多くのデータが失われます。 繰り返しますが、 DELETE



要求をすり抜けると、すべてが再び削除され、最初からやり直す必要があります(またはPITRのコールドバックアップを作成する必要があります)。







Postgresの遅延インスタンスを再起動し、指定された時間までWALセグメントを繰り返しました。 リクエストにより、この段階で進行状況を追跡できます。







 SELECT -- current location in WAL pg_last_xlog_replay_location(), -- current transaction timestamp (state of the replica) pg_last_xact_replay_timestamp(), -- current physical time now(), -- the amount of time still to be applied until recovery_target_time has been reached '2018-10-12 09:25:00+00'::timestamptz - pg_last_xact_replay_timestamp() as delay;
      
      





タイムスタンプが変更されない場合、回復は完了しています。 recovery_target_action



アクションを設定して、再生後にインスタンスを閉じる、進める、または一時停止することができます(デフォルトでは一時停止します)。







データベースは、その不運なリクエストの前の状態になりました。 これで、たとえば、データをエクスポートできます。 ショートカットに関するすべての削除されたデータと、タスクおよびマージ要求とのすべての接続をエクスポートし、作業データベースに転送しました。 損失が大規模な場合は、単純にレプリカを昇格させ、それをメインレプリカとして使用できます。 しかし、その後、すべての変更は、回復した瞬間に失われます。







タイムスタンプの代わりに、トランザクションIDを使用することをお勧めします。 log_statements = 'ddl'



を使用して、たとえばDDLステートメント( DROP TABLE



など)にこれらのIDを書き込むと便利です。 トランザクションIDがある場合、 recovery_target_xid



を取得し、 DELETE



要求の前にトランザクションに至るまですべてを実行します。







作業に戻るのは非常に簡単です。recovery.confからすべての変更を削除し、Postgresを再起動します。 まもなく、レプリカに8時間の遅延が再び表示され、今後のトラブルに対応できます。







回復の利点



コールドバックアップの代わりに遅延レプリカを使用すると、数時間アーカイブからイメージ全体を復元する必要がありません。 たとえば、基本的な2 TBのバックアップ全体を取得するには5時間かかります。 そして、(最悪の場合)目的の状態に回復するには、毎日のWAL全体を適用する必要があります。







遅延レプリカは、次の2つの点でコールドバックアップよりも優れています。







  1. アーカイブからベースバックアップ全体を取得する必要はありません。
  2. 繰り返す必要があるWALセグメントの固定8時間ウィンドウがあります。


また、WALからPITRを作成できるかどうかを常に確認します。WALアーカイブの損傷やその他の問題をすぐに確認し、遅延レプリカの遅れを監視します。







この例では、復旧に50分かかりました。つまり、速度は1時間あたり110 GBのWALデータでした(アーカイブはまだAWS S3にありました )。 合計で、問題を解決し、1.5時間でデータを復元しました。







結論:遅延レプリカが役立つ場所(およびそうでない場所)



誤ってデータを失い、設定された遅延内でこの災害に気付いた場合、応急処置ツールとして遅延複製を使用します。







ただし、レプリケーションはバックアップではないことに注意してください。

バックアップとレプリケーションの目標は異なります。 コールドバックアップは、誤ってDELETE



またはDROP TABLE



作成した場合に役立ちます。 コールドストレージからバックアップを作成し、テーブルまたはデータベース全体の以前の状態を復元します。 ただし、同時に、 DROP TABLE



クエリは、作業中のクラスター上のすべてのレプリカでほぼ即座に再生されるため、通常のレプリケーションではここに保存されません。 複製自体は、個別のサーバーがリースされているときにデータベースにアクセスできるようにし、負荷を分散します。







レプリカが遅延していても、データセンターがクラッシュしたり、隠れた損傷や、すぐに気付かない他のイベントが発生した場合、安全な場所にコールドバックアップが必要になることがあります。 1つの複製からは意味がありません。







ご注意 GitLab.comでは 、システムレベルでのみデータ損失から保護し、ユーザーレベルではデータを復元しません。








All Articles