Kuinka käytimme laiska replikointia katastrofipalautukseen PostgreSQL:n avulla

Kuinka käytimme laiska replikointia katastrofipalautukseen PostgreSQL:n avulla
Replikointi ei ole varmuuskopio. Tai ei? Näin käytimme laiskaa replikointia palauttamiseen poistamalla vahingossa pikakuvakkeita.

infrastruktuurin asiantuntijoita GitLab vastaa työstä GitLab.com - suurin GitLabin esiintymä luonnossa. 3 miljoonalla käyttäjällä ja lähes 7 miljoonalla projektilla se on yksi suurimmista avoimen lähdekoodin SaaS-sivustoista, jolla on oma arkkitehtuuri. Ilman PostgreSQL-tietokantajärjestelmää GitLab.com-infrastruktuuri ei pääse pitkälle, emmekä tee vikasietoisuutta mahdollisten vikojen varalta, jolloin voit menettää tietoja. On epätodennäköistä, että tällaista katastrofia tapahtuu, mutta valmistauduimme hyvin ja varusimme erilaisia ​​varmuuskopiointi- ja replikointimekanismeja.

Replikointi ei ole tietokannan varmuuskopiointityökalu (katso alla). Mutta nyt näemme kuinka nopeasti palauttaa vahingossa poistetut tiedot laiskalla replikaatiolla: päällä GitLab.com käyttäjä poistettu pikakuvake projektia varten gitlab-ce ja menetti yhteydet yhdistämispyyntöjen ja tehtävien kanssa.

Viivästyneen replikan ansiosta palautimme tiedot vain 1,5 tunnissa. Katso kuinka kävi.

Täsmällinen palautus PostgreSQL:llä

PostgreSQL:ssä on sisäänrakennettu toiminto, joka palauttaa tietokannan tilan tiettyyn ajankohtaan. Sitä kutsutaan Point-in-Time Recovery (PITR) ja käyttää samoja mekanismeja, jotka pitävät replikan ajan tasalla: alkaen luotettavasta tilannekuvasta koko tietokantaklusterista (perusvarmuuskopio), käytämme sarjan tilamuutoksia tiettyyn ajankohtaan asti.

Käyttääksemme tätä ominaisuutta kylmään varmuuskopiointiin teemme säännöllisesti perustietokannan varmuuskopion ja tallennamme sen arkistoon (GitLab-arkistot elävät Googlen pilvitallennustila). Valvomme myös tietokannan tilan muutoksia arkistoimalla eteenpäinkirjoitettavan lokin (kirjoittaa eteenpäin lokia, WAL). Ja kaiken tämän avulla voimme tehdä PITR:n katastrofipalautukseen: aloitamme tilannekuvasta, joka on otettu ennen virhettä ja otamme muutokset käyttöön WAL-arkistosta kaatumiseen asti.

Mikä on viivästynyt replikaatio?

Viivästetty replikointi tarkoittaa WAL-muutosten soveltamista viiveellä. Eli kauppa tapahtui tunnin aikana X, mutta se näkyy replikassa viiveellä d tunnissa X + d.

Fyysisen tietokannan replikan määrittämiseen PostgreSQL:ssä on kaksi tapaa: arkiston palautus ja suoratoiston replikointi. Palautetaan arkistosta, toimii pohjimmiltaan kuten PITR, mutta jatkuvasti: poimimme jatkuvasti muutoksia WAL-arkistosta ja käytämme niitä replikassa. A suoratoiston replikointi hakee WAL-virran suoraan ylävirran tietokantaisännästä. Suosimme palautusta arkistosta - se on helpompi hallita ja sen suorituskyky on normaali, mikä ei jää jäljelle tuotantoklusterista.

Kuinka määrittää viivästetty varmuuskopion palautus

Palautusvaihtoehdot kuvattu tiedostossa recovery.conf. Esimerkki:

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'

Näillä asetuksilla olemme määrittäneet viivästetyn replikan arkiston palautuksella. Käytetty täällä Wal-e poimia WAL-segmenttejä (restore_command) arkistosta, ja muutokset tulevat voimaan kahdeksan tunnin kuluttua (recovery_min_apply_delay). Replica tarkkailee arkistossa tapahtuvia aikajanan muutoksia, kuten klusterin vikasietoa (recovery_target_timeline).

С recovery_min_apply_delay voit määrittää latenssin suoratoiston replikoinnin, mutta replikointipaikkoihin, kuumaan varapalautteeseen ja niin edelleen liittyy muutama sudenkuoppa. WAL-arkisto välttää ne.

Parametri recovery_min_apply_delay ilmestyi vain PostgreSQL 9.3:ssa. Aiemmissa versioissa viivästetty replikointi vaatii yhdistelmän palautuksen hallintatoiminnot (pg_xlog_replay_pause(), pg_xlog_replay_resume()) tai pidä WAL-segmentit arkistossa viiveen ajan.

Miten PostgreSQL tekee sen?

On mielenkiintoista nähdä, kuinka PostgreSQL toteuttaa laiskan palautuksen. Katsotaanpa recoveryApplyDelay(XlogReaderState). Sitä kutsutaan kohteesta pääsilmukan toisto jokaista WAL-merkintää kohden.

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

Lopputulos on, että viive perustuu fyysiseen aikaan, joka on tallennettu tapahtumasitoumuksen aikaleimaan (xtime). Kuten näette, viive koskee vain sitoumuksia eikä vaikuta muihin tietueisiin - kaikki muutokset otetaan käyttöön suoraan ja toimitus viivästyy, joten näemme muutokset vasta määritetyn viiveen jälkeen.

Laiskan replikan käyttäminen tietojen palauttamiseen

Oletetaan, että meillä on tietokantaklusteri tuotannossa ja replika kahdeksan tunnin viiveellä. Katsotaanpa, kuinka tiedot palautetaan esimerkin avulla pikakuvakkeiden vahingossa poistaminen.

Kun huomasimme ongelman, me keskeytetty varmuuskopion palautus viivästetty replika:

SELECT pg_xlog_replay_pause();

Tauon jälkeen meillä ei ollut riskiä, ​​että kopio toistaisi pyynnön DELETE. Hyödyllinen asia, jos tarvitset aikaa kaiken selvittämiseen.

Tärkeintä on, että viivästyneen replikan on saavutettava pyyntöä edeltävä hetki DELETE. Tiesimme suunnilleen fyysisen poiston ajan. Poistimme recovery_min_apply_delay ja lisätty recovery_target_time в recovery.conf. Joten kopio saavuttaa oikean hetken viipymättä:

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

Aikaleimoilla on parempi vähentää ylijäämää, jotta se ei jää huomaamatta. Totta, mitä suurempi lasku, sitä enemmän menetämme tietoja. Jälleen, jos ohitamme pyynnön DELETE, kaikki poistetaan uudelleen ja sinun on aloitettava alusta (tai jopa otettava kylmä varmuuskopio PITR:stä).

Aloitimme viivästyneen Postgres-ilmentymän uudelleen ja WAL-segmentit toistettiin määritettyyn aikaan asti. Voit seurata edistymistä tässä vaiheessa kyselyllä:

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;

Jos aikaleima ei enää muutu, palautus on valmis. Voit mukauttaa toimintoa recovery_target_actionsulkea, edistää tai keskeyttää ilmentymän uudelleenyrityksen jälkeen (se keskeytyy oletuksena).

Tietokanta tuli tilaan ennen tuota epäonnista pyyntöä. Nyt voit esimerkiksi viedä tietoja. Olemme vieneet etätarratiedot ja kaikki linkit ongelmiin ja yhdistämispyyntöihin ja siirtäneet ne tuotantotietokantaan. Jos häviöt ovat suuria, voit yksinkertaisesti mainostaa kopiota ja käyttää sitä pääkappaleena. Mutta sitten kaikki muutokset menetetään sen hetken jälkeen, johon olemme toipuneet.

On parempi käyttää tapahtumatunnuksia aikaleimien sijaan. Nämä tunnukset on hyödyllistä tallentaa esimerkiksi DDL-lauseita varten (esim DROP TABLE), käyttämällä log_statements = 'ddl'. Jos meillä olisi tapahtumatunnus, ottaisimme recovery_target_xid ja suoritti kaiken tapahtumaan ennen pyyntöä DELETE.

Töihin paluu on hyvin yksinkertaista: poista kaikki muutokset kohteesta recovery.conf ja käynnistä postgres uudelleen. Pian vihjeessä on taas kahdeksan tunnin viive, ja olemme valmiita tuleviin ongelmiin.

Palautusedut

Viivästetyn replikan kanssa kylmän varmuuskopion sijaan sinun ei tarvitse viettää tuntikausia palauttamaan koko tilannekuvaa arkistosta. Tarvitsemme esimerkiksi viisi tuntia saadaksemme koko 2 Tt:n perusvarmuuskopion. Ja sitten sinun on vielä käytettävä koko päivittäinen WAL palautuaksesi haluttuun tilaan (pahimmassa tapauksessa).

Viivästetty kopio on parempi kuin kylmä varmuuskopio kahdella tavalla:

  1. Sinun ei tarvitse saada koko perusvarmuuskopiota arkistosta.
  2. On kiinteä kahdeksan tunnin WAL-segmenttien ikkuna, joka on toistettava.

Lisäksi tarkistamme jatkuvasti, voidaanko WAL:lle tehdä PITR-koodi, ja havaitsimme nopeasti WAL-arkiston korruption tai muita ongelmia seuraamalla viivästyneen replikan ruuhkaa.

Tässä esimerkissä palautus kesti 50 minuuttia, eli nopeus oli 110 Gt WAL-dataa tunnissa (arkisto oli edelleen päällä AWS S3). Kaiken kaikkiaan ratkaisimme ongelman ja palautimme tiedot 1,5 tunnissa.

Yhteenveto: missä viivästetty replika on hyödyllinen (ja missä ei)

Käytä viivästettyä replikointia ensiapuna, jos menetät vahingossa tietoja ja huomaat tämän katastrofin määritetyn viiveen sisällä.

Mutta muista: replikointi ei ole varmuuskopio.

Varmuuskopioinnilla ja replikaatiolla on eri tarkoitus. Kylmä varmuuskopio on hyödyllinen, jos teit vahingossa DELETE tai DROP TABLE. Teemme varmuuskopion kylmävarastosta ja palautamme taulukon tai koko tietokannan aiemman tilan. Mutta samalla pyyntö DROP TABLE toistetaan lähes välittömästi kaikissa toimivan klusterin replikoissa, joten tavallinen replikointi ei tallennu tähän. Itse replikointi pitää tietokannan saatavilla, kun yksittäiset palvelimet vuokrataan ja jakaa kuorman.

Jopa viivästyneen replikan kanssa tarvitsemme joskus todella kylmän varmuuskopion turvalliseen paikkaan, jos yhtäkkiä tapahtuu datakeskuksen vika, piilotettu vaurio tai muu tapahtuma, jota et heti huomaa. Tässä yhdestä replikaatiosta ei ole mitään järkeä.

Huomata. päälle GitLab.com suojaamme tällä hetkellä vain tietojen katoamiselta järjestelmätasolla emmekä palauta tietoja käyttäjätasolla.

Lähde: will.com

Lisää kommentti