Kuidas kasutasime PostgreSQL-iga katastroofi taastamiseks viivitatud replikatsiooni

Kuidas kasutasime PostgreSQL-iga katastroofi taastamiseks viivitatud replikatsiooni
Replikatsioon ei ole varukoopia. Või mitte? Siit saate teada, kuidas me kasutasime edasilükatud replikatsiooni, et kogemata otseteede kustutamisest taastuda.

Infrastruktuuri spetsialistid Töö eest vastutab GitLab GitLab.com - suurim GitLabi eksemplar looduses. 3 miljoni kasutaja ja peaaegu 7 miljoni projektiga on see üks suurimaid avatud lähtekoodiga SaaS-i saite, millel on spetsiaalne arhitektuur. Ilma PostgreSQL-i andmebaasita ei jõua GitLab.com infrastruktuur kaugele ja mida me teeme, et tagada tõrketaluvus tõrgete korral, kui andmed võivad kaduda. Sellise katastroofi juhtumine on ebatõenäoline, kuid oleme hästi ette valmistatud ja varustatud erinevate varundus- ja replikatsioonimehhanismidega.

Replikatsioon ei ole vahend andmebaaside varundamiseks (vaata allpool). Kuid nüüd näeme, kuidas kogemata kustutatud andmeid laiska replikatsiooni abil kiiresti taastada: sees GitLab.com kasutaja kustutas otsetee projekti jaoks gitlab-ce ja kaotasid ühendused liitmistaotluste ja ülesannetega.

Edasilükatud koopiaga taastasime andmed vaid 1,5 tunniga. Vaata, kuidas see juhtus.

Ajapunkti taastamine PostgreSQL-iga

PostgreSQL-il on sisseehitatud funktsioon, mis taastab andmebaasi oleku teatud ajahetkel. Seda nimetatakse Täpne taastamine (PITR) ja kasutab samu mehhanisme, mis hoiavad koopiat ajakohasena: alustades kogu andmebaasi klastri usaldusväärsest hetktõmmisest (baasvarukoopia), rakendame teatud ajahetkeni mitmeid olekumuudatusi.

Selle funktsiooni kasutamiseks külmvarundamiseks teeme regulaarselt andmebaasi põhivarukoopia ja salvestame selle arhiivi (GitLabi arhiivid elavad Google'i pilvesalvestus). Samuti jälgime andmebaasi oleku muutusi, arhiveerides ettekirjutamise logi (ette kirjutamise logi, WAL). Ja kui see kõik on paigas, saame teha katastroofi taastamiseks PITR-i: alustades enne tõrget tehtud hetktõmmistest ja rakendades muudatusi WAL-i arhiivist kuni tõrkeni.

Mis on edasilükatud replikatsioon?

Laisk replikatsioon on WAL-i muudatuste rakendamine viivitusega. See tähendab, et tehing toimus tunniga X, kuid see ilmub koopiasse viivitusega d tunni pärast X + d.

PostgreSQL-il on füüsilise andmebaasi koopia seadistamiseks kaks võimalust: varukoopia taastamine ja voogesituse replikatsioon. Taastamine arhiivist, töötab põhimõtteliselt nagu PITR, kuid pidevalt: hangime pidevalt WAL-i arhiivist muudatusi ja rakendame need koopiale. A voogesituse replikatsioon otsib WAL-voo otse ülesvoolu andmebaasi hostist. Eelistame arhiivide taastamist – seda on lihtsam hallata ja see on normaalse jõudlusega, mis hoiab tootmisklastriga sammu.

Kuidas seadistada arhiivist viivitatud taastamist

Taastevalikud failis kirjeldatud recovery.conf... Näide:

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'

Nende parameetritega konfigureerisime edasilükatud koopia koos varukoopia taastamisega. Siin seda kasutatakse wal-e eraldada WAL segmente (restore_command) arhiivist ja muudatused rakenduvad kaheksa tunni pärast (recovery_min_apply_delay). Replika jälgib arhiivis ajaskaala muudatusi, näiteks klastri tõrkesiirde tõttu (recovery_target_timeline).

С recovery_min_apply_delay Saate seadistada voogesituse replikatsiooni viivitusega, kuid siin on paar lõksu, mis on seotud replikatsioonipesade, kuuma ooterežiimi tagasisidega ja nii edasi. WAL-i arhiiv võimaldab teil neid vältida.

Parameeter recovery_min_apply_delay ilmus ainult PostgreSQL 9.3-s. Varasemates versioonides peate edasilükatud replikatsiooni jaoks kombinatsiooni konfigureerima taastamise juhtimise funktsioonid (pg_xlog_replay_pause(), pg_xlog_replay_resume()) või hoidke WAL-i segmente viivituse ajaks arhiivis.

Kuidas PostgreSQL seda teeb?

Huvitav on näha, kuidas PostgreSQL rakendab laiska taastamist. Vaatame edasi recoveryApplyDelay(XlogReaderState). Seda kutsutakse alates peamine kordussilmus iga WAL-i sissekande kohta.

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

Lõpptulemus on see, et viivitus põhineb füüsilisel ajal, mis on salvestatud tehingu sooritamise ajatemplisse (xtime). Nagu näete, kehtib viivitus ainult sissekannete kohta ja ei mõjuta teisi kirjeid – kõik muudatused rakendatakse otse ja commit viibib, seega näeme muudatusi alles pärast seadistatud viivitust.

Kuidas kasutada andmete taastamiseks viivitatud koopiat

Oletame, et meil on andmebaasi klaster ja koopia, mille tootmise viivitus on kaheksa tundi. Vaatame, kuidas näite abil andmeid taastada kogemata otseteede kustutamine.

Kui saime probleemist teada arhiivi taastamine on peatatud edasilükatud koopia jaoks:

SELECT pg_xlog_replay_pause();

Pausi korral ei olnud meil ohtu, et koopia taotlust kordaks DELETE. Kasulik asi, kui vajate aega, et kõike välja mõelda.

Asi on selles, et edasilükatud koopia peab jõudma päringueelsesse hetke DELETE. Teadsime ligikaudselt eemaldamise füüsilist aega. Oleme kustutanud recovery_min_apply_delay ja lisas recovery_target_time в recovery.conf. Nii jõuab koopia viivitamata õigele hetkele:

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

Ajatemplitega on parem ülejääki vähendada, et mitte mööda minna. Tõsi, mida suurem on langus, seda rohkem andmeid kaotame. Jällegi, kui me jätame taotluse vahele DELETE, kustutatakse kõik uuesti ja peate otsast alustama (või isegi PITR-i jaoks külma varukoopia tegema).

Taaskäivitasime edasilükatud Postgresi eksemplari ja WAL-i segmente korrati kuni määratud ajani. Selles etapis saate edenemist jälgida, küsides:

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;

Kui ajatempel enam ei muutu, on taastamine lõppenud. Tegevust saab kohandada recovery_target_actioneksemplari sulgemiseks, reklaamimiseks või peatamiseks pärast uuesti proovimist (see on vaikimisi peatatud).

Andmebaas naasis oma olekusse enne seda kahetsusväärset taotlust. Nüüd saate näiteks andmeid eksportida. Eksportisime kustutatud sildiandmed ja kõik probleemide ja liitmistaotluste lingid ning teisaldasime need tootmisandmebaasi. Kui kaod on suuremahulised, saate lihtsalt koopiat reklaamida ja kasutada seda peamisena. Kuid siis kaovad kõik muutused pärast seda punkti, milleni oleme taastunud.

Ajatemplite asemel on parem kasutada tehingu ID-sid. Kasulik on need ID-d salvestada näiteks DDL-i avalduste jaoks (nt DROP TABLE), kasutades log_statements = 'ddl'. Kui meil oleks tehingu ID, siis võtaksime recovery_target_xid ja jooksis kõik tehinguni enne päringut DELETE.

Tööle naasmine on väga lihtne: eemaldage kõik muudatused recovery.conf ja taaskäivitage Postgres. Koopial on peagi taas kaheksatunnine viivitus ja me oleme tulevasteks probleemideks valmis.

Taastamise eelised

Külma varukoopia asemel edasilükatud koopiaga ei pea te kulutama tunde kogu pildi arhiivist taastamiseks. Näiteks kogu põhilise 2 TB varukoopia hankimiseks kulub meil viis tundi. Ja siis peate ikkagi rakendama kogu päeva WAL-i, et soovitud olekusse taastuda (halvimal juhul).

Edasilükatud koopia on parem kui külmvarukoopia kahel viisil.

  1. Kogu põhivarukoopiat pole vaja arhiivist eemaldada.
  2. Seal on fikseeritud kaheksatunnine WAL-segmentide aken, mida tuleb korrata.

Samuti kontrollime pidevalt, kas WAL-ist on võimalik PITR-i teha, ning me märkaksime kiiresti WAL-i arhiivi korruptsiooni või muid probleeme, jälgides edasilükatud koopia viivitust.

Selles näites kulus meil taastamiseks 50 minutit, mis tähendab, et kiirus oli 110 GB WAL-andmeid tunnis (arhiiv oli endiselt sisse lülitatud AWS S3). Kokkuvõttes lahendasime probleemi ja taastasime andmed 1,5 tunniga.

Tulemused: kus edasilükatud koopia on kasulik (ja kus mitte)

Kasutage viivitatud replikatsiooni esmaabina, kui kaotasite kogemata andmed ja märkasite seda probleemi konfigureeritud viivituse jooksul.

Kuid pidage meeles: replikatsioon ei ole varukoopia.

Varundamisel ja replikatsioonil on erinevad eesmärgid. Külm varukoopia tuleb kasuks, kui selle kogemata tegite DELETE või DROP TABLE. Teeme külmhoidlast varukoopia ja taastame tabeli või kogu andmebaasi eelmise oleku. Aga samas palve DROP TABLE reprodutseeritakse peaaegu kohe kõigis tööklastri koopiates, nii et tavaline replikatsioon siin ei aita. Replikatsioon ise hoiab andmebaasi kättesaadavana, kui üksikud serverid on maas, ja jaotab koormuse.

Isegi edasilükatud koopia puhul vajame mõnikord tõesti külma varukoopiat turvalises kohas, kui ilmnevad andmekeskuse rike, varjatud kahjustused või muud sündmused, mida pole kohe märgata. Ainuüksi replikatsioonist pole siin kasu.

Märkus. edasi GitLab.com Andmete kadumise eest kaitseme praegu ainult süsteemi tasemel ega taasta andmeid kasutaja tasemel.

Allikas: www.habr.com

Lisa kommentaar