Hogyan használtuk a lusta replikációt a katasztrófa utáni helyreállításhoz a PostgreSQL-lel

Hogyan használtuk a lusta replikációt a katasztrófa utáni helyreállításhoz a PostgreSQL-lel
A replikáció nem biztonsági másolat. Vagy nem? Így használjuk a késleltetett replikációt a parancsikonok véletlen törlése utáni helyreállításhoz.

Infrastrukturális szakemberek A munkáért a GitLab a felelős GitLab.com - a legnagyobb GitLab példány a természetben. 3 millió felhasználójával és közel 7 millió projektjével az egyik legnagyobb nyílt forráskódú SaaS-webhely dedikált architektúrával. A PostgreSQL adatbázisrendszer nélkül a GitLab.com infrastruktúra nem fog messzire menni, és mit teszünk annak érdekében, hogy hibatűrést biztosítsunk olyan hibák esetén, amikor adatok elveszhetnek. Nem valószínű, hogy ilyen katasztrófa megtörténik, de jól felkészültünk, és fel van szerelve különféle biztonsági mentési és replikációs mechanizmusokkal.

A replikáció nem az adatbázisok biztonsági mentésének eszköze (lásd alább). De most meglátjuk, hogyan lehet gyorsan visszaállítani a véletlenül törölt adatokat a lusta replikáció segítségével: be GitLab.com használó törölte a parancsikont a projekthez gitlab-ce és megszakadt a kapcsolat az egyesítési kérésekkel és feladatokkal.

A késleltetett replikával mindössze 1,5 óra alatt helyreállítottuk az adatokat. Nézd, hogyan történt.

Pontos helyreállítás a PostgreSQL-lel

A PostgreSQL beépített funkcióval rendelkezik, amely visszaállítja az adatbázis állapotát egy adott időpontban. Ez az úgynevezett Pontos helyreállítás (PITR), és ugyanazokat a mechanizmusokat használja, amelyek a replikát naprakészen tartják: a teljes adatbázis-fürt megbízható pillanatképével (alapmentés) kezdve állapotváltozások sorozatát alkalmazzuk egy bizonyos időpontig.

Ahhoz, hogy ezt a funkciót hideg mentésre használhassuk, rendszeresen készítünk egy alapvető adatbázis-mentést, és azt egy archívumban tároljuk (a GitLab archívumai Google felhőtárhely). Figyelemmel kísérjük az adatbázis állapotának változásait is az előreírási napló archiválásával (előre írható napló, WAL). Mindezek mellett pedig elvégezhetünk egy PITR-t a katasztrófa utáni helyreállításhoz: kezdve a hiba előtt készült pillanatfelvétellel, és a WAL-archívumtól a meghibásodásig alkalmazva a változtatásokat.

Mi az a késleltetett replikáció?

A lusta replikáció a WAL módosításainak késleltetett alkalmazása. Vagyis a tranzakció egy óra alatt megtörtént X, de késéssel jelenik meg a replikában d egy óra múlva X + d.

A PostgreSQL-nek két módja van a fizikai adatbázis-replika beállítására: a biztonsági mentés helyreállítása és az adatfolyam-replikáció. Visszaállítás archívumból, lényegében úgy működik, mint a PITR, de folyamatosan: folyamatosan lekérjük a változtatásokat a WAL archívumból és alkalmazzuk a replikára. A streaming replikáció közvetlenül lekéri a WAL adatfolyamot az upstream adatbázis gazdagéptől. Inkább az archívum helyreállítását részesítjük előnyben – könnyebben kezelhető, és normál teljesítményű, amely lépést tart az éles klaszterrel.

Hogyan állíthat be késleltetett helyreállítást archívumból

Helyreállítási lehetőségek fájlban leírtak szerint recovery.conf... Példa:

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'

Ezekkel a paraméterekkel konfiguráltunk egy késleltetett replikát biztonsági mentés helyreállításával. Itt használják wal-e WAL szegmensek kivonásához (restore_command) az archívumból, és a változtatások nyolc óra elteltével lépnek életbe (recovery_min_apply_delay). A replika figyeli az idővonal változásait az archívumban, például a fürt feladatátvétele miatt (recovery_target_timeline).

С recovery_min_apply_delay Beállíthatja az adatfolyam-replikációt késleltetéssel, de van itt néhány buktató, amelyek a replikációs helyekkel, a gyors készenléti visszajelzésekkel és így tovább kapcsolatosak. A WAL archívum lehetővé teszi ezek elkerülését.

Paraméter recovery_min_apply_delay csak a PostgreSQL 9.3-ban jelent meg. A korábbi verziókban a halasztott replikációhoz konfigurálnia kell a kombinációt helyreállítási menedzsment funkciók (pg_xlog_replay_pause(), pg_xlog_replay_resume()) vagy tartsa a WAL szegmenseket archívumban a késleltetés idejére.

Hogyan teszi ezt a PostgreSQL?

Érdekes látni, hogy a PostgreSQL hogyan valósítja meg a lusta helyreállítást. Nézzük recoveryApplyDelay(XlogReaderState). -ről hívják fő ismétlési hurok minden egyes WAL bejegyzéshez.

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;
}

A lényeg az, hogy a késleltetés a tranzakció véglegesítési időbélyegében rögzített fizikai időn alapul (xtime). Amint láthatja, a késleltetés csak a véglegesítésekre vonatkozik, és nem érinti a többi bejegyzést – minden változás közvetlenül érvényesül, a véglegesítés pedig késik, így a változásokat csak a beállított késleltetés után fogjuk látni.

Késleltetett replika használata adatok visszaállítására

Tegyük fel, hogy van egy adatbázis-fürtünk és egy replikánk nyolc órás késéssel a termelésben. Nézzük meg, hogyan lehet visszaállítani az adatokat egy példa segítségével parancsikonok véletlen törlése.

Amikor megtudtuk a problémát, mi az archívum helyreállítása szünetel késleltetett replika esetén:

SELECT pg_xlog_replay_pause();

Egy szünettel nem volt kockázatunk annak, hogy a replika megismétli a kérést DELETE. Hasznos dolog, ha időre van szüksége, hogy mindent kitaláljon.

A lényeg az, hogy a késleltetett replikának el kell érnie a kérés előtti pillanatot DELETE. Körülbelül tudtuk az eltávolítás fizikai idejét. töröltük recovery_min_apply_delay és hozzáadott recovery_target_time в recovery.conf. Így éri el a replika késedelem nélkül a megfelelő pillanatot:

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

Az időbélyegekkel jobb csökkenteni a felesleget, hogy ne maradjon le. Igaz, minél nagyobb a csökkenés, annál több adatot veszítünk. Még egyszer, ha elvétjük a kérést DELETE, minden újra törlődik, és elölről kell kezdenie (vagy akár hidegmentést kell készítenie a PITR-hez).

Újraindítottuk a halasztott Postgres-példányt, és a WAL-szegmenseket a megadott ideig ismételtük. Ebben a szakaszban nyomon követheti a haladást, ha megkérdezi:

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;

Ha az időbélyeg már nem változik, a helyreállítás befejeződött. A művelet testreszabható recovery_target_actiona példány bezárásához, előléptetéséhez vagy szüneteltetéséhez az újrapróbálkozás után (alapértelmezés szerint felfüggesztve van).

Az adatbázis visszatért a szerencsétlen kérés előtti állapotába. Most például adatokat exportálhat. Exportáltuk a törölt címkeadatokat, valamint a problémákra és egyesítési kérelmekre mutató hivatkozásokat, és áthelyeztük őket az éles adatbázisba. Ha a veszteségek nagy léptékűek, egyszerűen reklámozhatja a replikát, és használhatja főként. De akkor minden változás elveszik azon pont után, ahová helyreálltunk.

Az időbélyegek helyett jobb tranzakcióazonosítókat használni. Hasznos ezeket az azonosítókat rögzíteni, például DDL utasításokhoz (pl DROP TABLE), használva log_statements = 'ddl'. Ha lenne tranzakcióazonosítónk, vennénk recovery_target_xid és mindent lefuttattak a tranzakcióig a kérés előtt DELETE.

A munkához való visszatérés nagyon egyszerű: távolítsa el az összes módosítást a következőről: recovery.conf és indítsa újra a Postgres-t. A replika hamarosan ismét nyolc órát késik, és felkészültünk a jövőbeni bajokra.

Helyreállítási előnyök

Hideg biztonsági mentés helyett késleltetett replikával nem kell órákat töltenie a teljes kép archívumból való visszaállításával. Például öt órába telik, hogy megszerezzük a teljes alap 2 TB-os biztonsági mentést. És akkor még mindig alkalmaznia kell a teljes napi WAL-t, hogy visszaálljon a kívánt állapotba (a legrosszabb esetben).

A késleltetett replika kétféleképpen jobb, mint egy hideg biztonsági mentés:

  1. Nem szükséges eltávolítani a teljes alapvető biztonsági másolatot az archívumból.
  2. Van egy rögzített nyolc órás WAL-szegmens ablak, amelyet meg kell ismételni.

Folyamatosan ellenőrizzük azt is, hogy lehet-e PITR-t készíteni a WAL-ból, és a késleltetett replika késleltetésével gyorsan észrevennénk a WAL-archívum sérülését vagy egyéb problémáit.

Ebben a példában 50 percet vett igénybe a visszaállítás, ami azt jelenti, hogy óránként 110 GB WAL-adat volt (az archívum továbbra is bekapcsolva volt AWS S3). Összességében 1,5 óra alatt megoldottuk a problémát és helyreállítottuk az adatokat.

Eredmények: hol hasznos a halasztott replika (és hol nem)

Használja a késleltetett replikációt elsősegélyként, ha véletlenül elveszett az adat, és a konfigurált késleltetésen belül észlelte ezt a problémát.

De ne feledje: a replikáció nem biztonsági másolat.

A biztonsági mentésnek és a replikációnak különböző céljai vannak. A hideg biztonsági mentés jól jön, ha véletlenül készített DELETE vagy DROP TABLE. Hűtőtárhelyről biztonsági mentést készítünk, és visszaállítjuk a tábla vagy a teljes adatbázis korábbi állapotát. De ugyanakkor a kérés DROP TABLE szinte azonnal reprodukálódik a működő fürt összes replikájában, így a szokásos replikáció itt nem segít. A replikáció maga tartja rendelkezésre az adatbázist, amikor az egyes kiszolgálókat bérbe adják, és elosztja a terhelést.

Még egy késleltetett replika esetén is néha valóban szükségünk van egy biztonságos helyre való hidegmentésre, ha adatközponti meghibásodás, rejtett sérülés vagy más, nem azonnal észrevehető esemény történik. A replikáció önmagában itt nem használ.

Megjegyzés. tovább GitLab.com Jelenleg csak rendszerszinten védekezünk az adatvesztés ellen, felhasználói szinten nem állítunk vissza adatokat.

Forrás: will.com

Hozzászólás