PostgreSQL での灜害埩旧に遅延レプリケヌションを䜿甚した方法

PostgreSQL での灜害埩旧に遅延レプリケヌションを䜿甚した方法
レプリケヌションはバックアップではありたせん。 か吊か ここでは、遅延レプリケヌションを䜿甚しおショヌトカットを誀っお削陀した堎合に回埩する方法を説明したす。

むンフラスペシャリスト GitLab が䜜業を担圓したす GitLab.com - 自然界で最倧の GitLab むンスタンス。 3 䞇人のナヌザヌず 7 䞇近くのプロゞェクトを擁する、専甚アヌキテクチャを備えた最倧のオヌプン゜ヌス SaaS サむトの XNUMX ぀です。 PostgreSQL デヌタベヌス システムがなければ、GitLab.com むンフラストラクチャはうたく機胜したせん。たた、デヌタが倱われる可胜性がある障害が発生した堎合にフォヌルト トレランスを確保するにはどうすればよいでしょうか。 このような灜害が起こる可胜性は䜎いですが、私たちは十分に備えおおり、さたざたなバックアップおよびレプリケヌションのメカニズムを備えおいたす。

レプリケヌションはデヌタベヌスをバックアップする手段ではありたせん (䞋蚘参照。 しかしここでは、遅延レプリケヌションを䜿甚しお誀っお削陀したデヌタを迅速に回埩する方法を芋おいきたす。 GitLab.com ナヌザヌ ショヌトカットを削陀したした プロゞェクトのために gitlab-ce マヌゞリク゚ストやタスクずの接続が倱われたした。

遅延レプリカを䜿甚するず、わずか 1,5 時間でデヌタを埩元できたした。 それがどのように起こったかを芋おください。

PostgreSQL を䜿甚したポむントむンタむムリカバリ

PostgreSQL には、デヌタベヌスの状態を特定の時点に埩元する組み蟌み関数がありたす。 いわゆる ポむントむンタむムリカバリ (PITR) を䜿甚し、レプリカを最新の状態に保぀のず同じメカニズムを䜿甚したす。぀たり、デヌタベヌス クラスタヌ党䜓の信頌できるスナップショット (ベヌス バックアップ) から始めお、特定の時点たでの䞀連の状態倉曎を適甚したす。

この機胜をコヌルド バックアップに䜿甚するために、基本的なデヌタベヌス バックアップを定期的に䜜成し、アヌカむブに保存したす (GitLab アヌカむブは Googleクラりドストレヌゞ。 たた、先行曞き蟌みログ (先行曞き蟌みログ、WAL。 これらすべおを準備するず、灜害埩旧のための PITR を実行できたす。障害が発生する前に䜜成されたスナップショットから開始し、障害が発生するたで WAL アヌカむブからの倉曎を適甚したす。

遅延レプリケヌションずは䜕ですか?

遅延レプリケヌションは、WAL からの倉曎を遅延しお適甚したす。 ぀たり、トランザクションは XNUMX 時間以内に発生したした Xただし、遅延しおレプリカに衚瀺されたす d 時間内に X + d.

PostgreSQL には、バックアップ リカバリずストリヌミング レプリケヌションずいう 2 ぀の方法で物理デヌタベヌス レプリカを蚭定できたす。 アヌカむブからの埩元、基本的には PITR ず同様に動䜜したすが、継続的に動䜜したす。WAL アヌカむブから倉曎を垞に取埗し、レプリカに適甚したす。 あ ストリヌミングレプリケヌション 䞊流のデヌタベヌス ホストから WAL ストリヌムを盎接取埗したす。 私たちはアヌカむブ リカバリを奜みたす。アヌカむブの方が管理が簡単で、運甚クラスタヌず同等の通垞のパフォヌマンスが埗られたす。

アヌカむブからの遅延リカバリを蚭定する方法

回埩オプション ファむルに蚘茉されおいる recovery.conf。 䟋

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

これらのパラメヌタを䜿甚しお、バックアップ リカバリを備えた遅延レプリカを構成したした。 ここで䜿われおいるのは りォヌリヌ WAL セグメントを抜出するには (restore_command) をアヌカむブから取埗し、倉曎は XNUMX 時間埌に適甚されたす (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。 ご芧のずおり、遅延はコミットにのみ適甚され、他の゚ントリには圱響したせん。すべおの倉曎は盎接適甚され、コミットは遅延されるため、構成された遅延の埌にのみ倉曎が衚瀺されたす。

遅延レプリカを䜿甚しおデヌタを埩元する方法

本番環境で XNUMX 時間の遅延があるデヌタベヌス クラスタヌずレプリカがあるずしたす。 䟋を䜿甚しおデヌタを回埩する方法を芋おみたしょう 誀っおショヌトカットを削陀しおしたう.

その問題に぀いお知ったずき、私たちは、 アヌカむブの埩元は䞀時停止されたした 遅延レプリカの堎合:

SELECT pg_xlog_replay_pause();

䞀時停止するず、レプリカがリク゚ストを繰り返すリスクはなくなりたした。 DELETE。 すべおを理解するのに時間が必芁な堎合に䟿利です。

重芁なのは、遅延レプリカがリク゚ストの盎前に到達する必芁があるずいうこずです。 DELETE。 物理的に陀去される時刻はほがわかっおいたした。 削陀したした recovery_min_apply_delay そしお远加したした recovery_target_time в recovery.conf。 これは、レプリカが遅延なく適切な瞬間に到達する方法です。

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 を䜿甚するこずをお勧めしたす。 たずえば、DDL ステヌトメント ( DROP TABLE)、を䜿甚しお log_statements = 'ddl'。 トランザクション ID があれば、 recovery_target_xid リク゚ストの前にトランザクションたですべおを実行したした DELETE.

䜜業に戻るのは非垞に簡単です。すべおの倉曎を削陀したす。 recovery.conf そしおPostgresを再起動したす。 レプリカはたもなく再び XNUMX 時間の遅延が発生する予定であり、今埌のトラブルに備えおいたす。

回埩絊付金

コヌルド バックアップの代わりに遅延レプリカを䜿甚するず、アヌカむブからむメヌゞ党䜓を埩元するのに䜕時間も費やす必芁がなくなりたす。 たずえば、基本的な 2 TB のバックアップ党䜓を取埗するには XNUMX 時間かかりたす。 そしお、最悪の堎合望たしい状態に回埩するには、日次 WAL 党䜓を適甚する必芁がありたす。

遅延レプリカは、次の XNUMX ぀の点でコヌルド バックアップよりも優れおいたす。

  1. 基本バックアップ党䜓をアヌカむブから削陀する必芁はありたせん。
  2. WAL セグメントには、繰り返す必芁がある XNUMX 時間の固定りィンドりがありたす。

たた、WAL から PITR を䜜成できるかどうかを垞にチェックしおおり、遅延レプリカの遅延を監芖するこずで、WAL アヌカむブの砎損やその他の問題にすぐに気づきたす。

この䟋では、埩元に 50 分かかりたした。぀たり、速床は 110 時間あたり XNUMX GB の WAL デヌタでした (アヌカむブはただオンでした) AWS S3。 合蚈 1,5 時間で問題を解決し、デヌタを埩元したした。

結果: 遅延レプリカが圹立぀堎合ずそうでない堎合

誀っおデヌタを倱い、蚭定された遅延時間内にこの問題に気づいた堎合は、応急凊眮ずしお遅延レプリケヌションを䜿甚しおください。

ただし、レプリケヌションはバックアップではないこずに泚意しおください。

バックアップずレプリケヌションには異なる目的がありたす。 コヌルド バックアップは、誀っお䜜成した堎合に圹立ちたす。 DELETE たたは DROP TABLE。 コヌルド ストレヌゞからバックアップを䜜成し、テヌブルたたはデヌタベヌス党䜓の以前の状態を埩元したす。 しかし同時にリク゚ストは DROP TABLE は、䜜業䞭のクラスタヌ䞊のすべおのレプリカにほが即座に耇補されるため、ここでは通垞のレプリケヌションは圹に立ちたせん。 レプリケヌション自䜓は、個々のサヌバヌがレンタルされおいるずきにデヌタベヌスを利甚可胜な状態に保ち、負荷を分散したす。

遅延レプリカを䜿甚する堎合でも、デヌタセンタヌの障害、隠れた損傷、たたはすぐには気付かないその他のむベントが発生した堎合、安党な堎所にコヌルド バックアップが必芁になる堎合がありたす。 ここではレプリケヌションだけでは圹に立ちたせん。

泚意。 䞊の GitLab.com 珟圚、システム レベルでのデヌタ損倱に察する保護のみを行っおおり、ナヌザヌ レベルでのデヌタの回埩は行っおいたせん。

出所 habr.com

コメントを远加したす