Hogyan használtuk a késleltetett replikációt vészhelyzeti helyreállításhoz PostgreSQL-lel

Hogyan használtuk a késleltetett replikációt vészhelyzeti helyreállításhoz PostgreSQL-lel
A replikáció nem biztonsági mentés. Vagy mégis? Íme, hogyan használtuk a késleltetett replikációt a véletlenül törölt linkek helyreállításához.

Infrastruktúra szakértők a GitLabnál felelnek a működésért GitLab.com — a legnagyobb GitLab példány a világon. Itt 3 millió felhasználó és közel 7 millió projekt található, és ez az egyik legnagyobb nyílt forráskódú SaaS weboldal dedikált architektúrával. PostgreSQL adatbázis rendszer nélkül a GitLab.com infrastruktúrája nem menne messze, és mindent megteszünk az adatvesztés eseten történő hibamentesség érdekében. Valószínűtlen, hogy ilyen katasztrófa bekövetkezik, de alaposan felkészültünk és különböző biztonsági mentési és replikációs mechanizmusokkal készültünk.

A replikáció nem adatbázis biztonsági mentés(lásd alább). De most megnézzük, hogyan lehet gyorsan helyreállítani a véletlenül törölt adatokat késleltetett replikációval: amikor GitLab.com a felhasználó törölte a linket a projekt számára gitlab-ce és elvesztette a kapcsolatot az összeolvasztási kérésekkel és feladatokkal.

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

Időpont szerinti helyreállítás PostgreSQL-lel

A PostgreSQL rendelkezik egy beépített funkcióval, amely lehetővé teszi az adatbázis állapotának helyreállítását egy adott időpontban. Ezt nevezik Point-in-Time Recovery (PITR) és ugyanazokat a mechanizmusokat használja, amelyek támogatják a replikák aktualitását: egy megbízható pillanatfelvételtől kezdve az egész adatbázis klaszterről (alap biztonsági mentés) egy sor változtatást alkalmazunk egy adott időpontig.

E funkció használatához hideg biztonsági mentéshez rendszeresen készítünk alap biztonsági mentést az adatbázisról, és archiváljuk azt (a GitLab archívumok a Google felhőtárolójában). Ezen kívül nyomon követjük az adatbázis állapotának változásait, archiválva az előre írási naplót (write-ahead log, WAL). Ezzel pedig elvégezhetjük a PITR-t a vészhelyzeti helyreállításhoz: kezdjük a hiba előtti pillanatfelvétellel, és alkalmazzuk a WAL archívumból származó változásokat a hibáig.

Mi az a késleltetett replikáció?

A késleltetett replikáció a WAL-ból származó változtatások késleltetett alkalmazását jelenti. Tehát a tranzakció X órakor történt, Xde a replikán késlekedéssel fog megjelenni, d X órában X + d.

A PostgreSQL-ban két módja van az adatbázis fizikai replikájának beállítására: archívum helyreállítása és streaming replikáció. Archívum helyreállítása, lényegében úgy működik, mint a PITR, de folyamatosan: folyamatosan kinyerjük a változásokat a WAL archívumból és alkalmazzuk azokat a replikán. A streaming replikáció közvetlenül kinyeri a WAL adatfolyamot a magasabb szintű adatbázis gazdától. Az archívum helyreállítását preferáljuk — könnyebb kezelni, és normális teljesítményt nyújt, amely nem marad el a működő klasztertől.

Hogyan állítsuk be az archívum helyreállítását késleltetve

Helyreállítási beállítások a következő fájlban található 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 beállításokkal állítottuk be az archívum helyreállítása révén a késleltetett replikát. Itt a wal-e használatos a WAL szegmensek kinyeréséhez (restore_command) az archívumból, és a változásokat nyolc órán belül fogják alkalmazni (recovery_min_apply_delay). A replikának figyelemmel kell kísérnie a változásokat az archívum idővonalán, például a klaszterben fellépő hiba miatt (recovery_target_timeline).

Késleltetett streaming replikációt is beállíthatunk, de van néhány csapda, amelyek a replikációs slotokkal, a forró tartalék visszajelzésével stb. kapcsolatosak. A WAL archívum lehetővé teszi, hogy elkerüljük ezeket. recovery_min_apply_delay csak a PostgreSQL 9.3-ban jelent meg. A korábbi verziókban a késleltetett replikációhoz egy kombinációt kellett beállítani

A parameter recovery_min_apply_delay helyreállítási vezérlési funkciókból pg_xlog_replay_pause(), pg_xlog_replay_resume() () vagy a WAL szegmenseket meg kellett tartani az archívumban a késleltetés idejére.Hogyan végzi mindezt a PostgreSQL?

Érdekes megnézni, hogyan valósítja meg a PostgreSQL a késleltetett helyreállítást. Nézzük meg a

recoveryApplyDelay(XlogReaderState) . Ez a fő ismétlési ciklusból hívható megminden egyes WAL bejegyzéshez. minden WAL bejegyzéshez. minden egyes bejegyzéshez a WAL-ból.

static bool
recoveryApplyDelay(XLogReaderState *record)
{
    uint8       xact_info;
    TimestampTz xtime;
    long        secs;
    int         microsecs;

    /* semmi teendő, ha nincs beállítva késleltetés */
    if (recovery_min_apply_delay <= 0)
        return false;

    /* a késleltetés nem alkalmazható olyan adatbázison, amely még nem konzisztens */
    if (!reachedConsistency)
        return false;

    /**
     * Ez egy COMMIT rekord?
     *
     * Kifejezetten úgy döntünk, hogy nem késleltetjük az abortokat, mivel azoknak
     * nincs hatásuk az MVCC-ra. Már lehetővé tesszük olyan rekordok visszajátszását,
     * amelyeknek nincs időbélyegük, így már van lehetőség a korai ütközések okozta
     * problémákra a standbys szolgáltatásokon.
     * /
    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);

    /**
     * Kilépés a rögzített késleltetés aktiválása nélkül, ha már
     * eldőlt, mikor kell alkalmazni ezt a rekordot
     * /
    TimestampDifference(GetCurrentTimestamp(), recoveryDelayUntilTime,
                        &secs, &microsecs);
    if (secs <= 0 && microsecs <= 0)
        return false;

    while (true)
    {
        // Rövidítve:
        // Használj WaitLatch-t, amíg el nem érjük recoveryDelayUntilTime
        // és aztán
        break;
    }
    return true;
}

A lényeg az, hogy a késleltetés a tranzakció commit időbélyegében rögzítettxtime). Ahogyan látható, a késleltetés csak a commitokra vonatkozik, és nem érinti a többi rekordot — az összes változtatás közvetlenül alkalmazásra kerül, míg a commit késlekedik, így a változások csak a beállított késleltetés után válnak láthatóvá.

Hogyan használjunk késleltetett replikát az adatok visszaállításához

Tegyük fel, hogy van egy produkciós adatbázis klaszterünk és egy nyolc órás késlekedéssel rendelkező replikánk. Nézzük meg, hogyan állíthatjuk vissza az adatokat egy véletlenszerű hivatkozás törlés példáján..

Amikor értesültünk a problémáról, mi felfüggesztettük a visszaállítást az archívumból a késleltetett replikához:

SELECT pg_xlog_replay_pause();

A szünettel nem volt kockázatunk, hogy a replikát ismételje a lekérdezést DELETE. Hasznos dolog, ha időt kell szánnunk a dolgok átgondolására.

A lényeg az, hogy a késleltetett replikának el kell jutnia a lekérdezés előtti időponthoz. DELETETudtuk körülbelül a törlés időbélyegét. Töröltük recovery_min_apply_delay és hozzáadtuk recovery_target_time be. recovery.confÍgy a replikához a megfelelő időpontra jutunk késleltetés nélkül:

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

Az időbélyegekkel jobb kevesebbet levonni, hogy ne hibázzunk. Igaz, hogy minél többet vonunk le, annál több adatot veszítünk. Ismét, ha átugorjuk a lekérdezést, DELETEminden újra törlődik, és újra el kell kezdenünk (vagy hátulról kell vennünk hideg biztonsági mentést a PITR-folyamatához).

Újraindítottuk a késleltetett Postgres példányt, és a WAL szegmensek a megadott időpontig ismétlődtek. Ezen a ponton a haladás nyomon követésére a következő lekérdezést használhatjuk:

SELECT
  -- aktuális hely a WAL-ban
  pg_last_xlog_replay_location(),
  -- aktuális tranzakciós időbélyeg (a replikáció állapota)
  pg_last_xact_replay_timestamp(),
  -- aktuális fizikai idő
  now(),
  -- az az időtartam, amely még alkalmazásra vár, amíg a recovery_target_time el nem érkezik
  '2018-10-12 09:25:00+00'::timestamptz - pg_last_xact_replay_timestamp() as delay;

Ha az időbélyeg többé nem változik, a helyreállítás befejeződött. Beállítható a művelet recovery_target_action, hogy a példányt bezárja, előrébb mozgatja vagy szünetelteti a repeat után (alapértelmezés szerint szüneteltetik).

Az adatbázis visszatért annak a baljós lekérdezésnek az állapotába. Most például ki lehet exportálni az adatokat. Exportáltuk a törölt címkékről és minden feladattal és merge-kérelmekkel kapcsolatos kapcsolatról szóló adatokat, és áthelyeztük őket a munkaadatbázisba. Ha a veszteség mértéke nagy, egyszerűen előrébb mozgathatjuk a replikát, és használhatjuk mint fő adatbázist. De akkor minden változtatás elveszik attól a ponttól kezdve, amelyig visszaálltunk.

Időbélyegek helyett érdemes a tranzakciós azonosítókat használni. Hasznos ezeket az azonosítókat feljegyezni, például a DDL operátorok esetén (mint például DROP TABLE), a következővel: log_statements = 'ddl'. Ha lett volna tranzakciós azonosítónk, megkaptuk volna a recovery_target_xid -t, és minden tranzakciót futtattunk volna a lekérdezés előtti állapotig. DELETE.

Visszatérni a munkához nagyon egyszerű: távolítsa el az összes módosítást a recovery.conf -ből, és indítson újra Postgres-t. Hamarosan a replikában ismét megjelenik a nyolcórás késedelem, és készen állunk a jövőbeli kellemetlenségekre.

Előnyök a helyreállítás szempontjából

Késleltetett replikával a hideg biztonsági másolat helyett nem kell órákig visszaállítani az egész pillanatképet az archívumból. Például öt órára van szükségünk, hogy előhozzuk az alap biztonsági másolatot a 2 TB-os méretből. És további időt kell tölteni az egész napi WAL alkalmazására, hogy visszaálljunk a kívánt állapotba (a legrosszabb esetben).

A késleltetett replikának két szempontból jobb, mint a hideg biztonsági másolat:

  1. Nem kell az egész alap biztonsági másolatot előhoznunk az archívumból.
  2. Van egy rögzített nyolcórás ablak a WAL szegmensek ismétlésére.

Emellett folyamatosan ellenőrizzük, hogy a WAL-ból lehet-e PITR-t végezni, és gyorsan észlelnénk a WAL archívum sérüléseit vagy egyéb problémáit, figyelve a késleltetett replikára.

Ebben a példában 50 percet vett igénybe a helyreállítás, így a sebesség 110 GB WAL adatot jelentett óránként (az archívum akkor még mindig AWS S3). Összességében 1,5 óra alatt megoldottuk a problémát és helyreállítottuk az adatokat.

Összegzés: hol hasznos az elhalasztott replikáció (és hol nem)

Használja az elhalasztott replikációt elsősegélyként, ha véletlenül elvesztette az adatokat, és észrevette ezt a problémát a beállított késleltetésen belül.

De vegye figyelembe: a replikáció nem biztonsági mentés.

A biztonsági mentés és a replikáció különböző célokat szolgál. A hideg biztonsági mentés hasznos, ha véletlenül létrehozott DELETE vagy DROP TABLE. A hideg tárolóból biztonsági mentést készítünk, és visszaállítjuk a táblázat vagy az egész adatbázis előző állapotát. De eközben a kérés DROP TABLE majdnem azonnal reprodukálódik minden replikán a működő klaszterben, ezért a szokásos replikáció itt nem segít. Magában a replikáció fenntartja az adatbázis elérhetőségét, amikor egyes szerverek leállnak, és elosztja a terhelést.

Még az elhalasztott replikációval is néha nagyon szükségünk van a hideg biztonsági mentésre egy biztonságos helyen, ha váratlanul adatközponti hiba, rejtett sérülés vagy más olyan esemény történik, amit azonnal nem észlel. Itt az egyetlen replikáció nem elegendő.

Megjegyzés. A GitLab.com jelenleg csak a rendszer szintjén védjük az adatvesztést, és nem állítjuk vissza az adatokat a felhasználói szinten.

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster