Hvernig við notuðum seinkaða afritun til að endurheimta hörmungar með PostgreSQL

Hvernig við notuðum seinkaða afritun til að endurheimta hörmungar með PostgreSQL
Afritun er ekki öryggisafrit. Eða ekki? Hér er hvernig við notuðum frestað afritun til að endurheimta eftir að flýtileiðum var eytt óvart.

Innviðasérfræðingar GitLab ber ábyrgð á verkinu GitLab.com - stærsta GitLab tilvik í náttúrunni. Með 3 milljónir notenda og næstum 7 milljónir verkefna er það ein stærsta opna SaaS síða með sérstakan arkitektúr. Án PostgreSQL gagnagrunnskerfisins mun GitLab.com innviðir ekki ná langt, og hvað erum við að gera til að tryggja bilanaþol ef einhverjar bilanir verða þegar gögn geta glatast. Það er ólíklegt að slík hörmung muni gerast, en við erum vel undirbúin og búnir af ýmsum öryggisafritunar- og afritunaraðferðum.

Afritun er ekki leið til að taka öryggisafrit af gagnagrunnum (sjá fyrir neðan). En nú munum við sjá hvernig á að endurheimta gögn sem hafa verið eytt fyrir slysni með því að nota lata afritun: á GitLab.com notandi eyddi flýtileiðinni fyrir verkefnið gitlab-ce og glatað tengsl við sameiningarbeiðnir og verkefni.

Með frestað eftirlíkingu, endurheimtum við gögn á aðeins 1,5 klukkustund. Sjáðu hvernig það gerðist.

Endurheimt með PostgreSQL

PostgreSQL er með innbyggða aðgerð sem endurheimtir stöðu gagnagrunns á tiltekinn tímapunkt. Það er kallað Endurheimt á tímapunkti (PITR) og notar sömu aðferðir sem halda eftirmyndinni uppfærðri: frá og með áreiðanlegri skyndimynd af öllum gagnagrunnsþyrpingunni (grunnafrit), beitum við röð af ástandsbreytingum upp að ákveðnum tímapunkti.

Til að nota þennan eiginleika fyrir kalt öryggisafrit gerum við reglulega grunnafrit af gagnagrunni og geymum það í skjalasafni (GitLab skjalasafn er í Google skýjageymsla). Við fylgjumst einnig með breytingum á ástandi gagnagrunnsins með því að geyma áskriftarskrána í geymslu (skrifa fram í tímann, WAL). Og með allt þetta á sínum stað getum við gert PITR fyrir hamfarabata: Byrjað á skyndimyndinni sem var tekin fyrir bilunina og beitt breytingunum frá WAL skjalasafninu til bilunar.

Hvað er frestað afritun?

Lazy afritun er beiting breytinga frá WAL með töf. Það er, viðskiptin áttu sér stað á klukkustund X, en það mun birtast í eftirmyndinni með töf d innan við klukkutíma X + d.

PostgreSQL hefur 2 leiðir til að setja upp líkamlega gagnagrunnseftirmynd: endurheimt öryggisafrits og afritun streymis. Endurheimtir úr skjalasafni, virkar í raun eins og PITR, en stöðugt: við sækjum stöðugt breytingar úr WAL skjalasafninu og notum þær á eftirmyndina. A afritun streymis sækir WAL strauminn beint frá andstreymis gagnagrunnshýslinum. Við viljum frekar endurheimta skjalasafna - það er auðveldara að stjórna því og hefur eðlilega afköst sem fylgir framleiðsluklasanum.

Hvernig á að setja upp seinkaðan bata úr skjalasafni

Endurheimtarvalkostir lýst í skránni recovery.conf. Dæmi:

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'

Með þessum breytum stilltum við frestað eftirmynd með endurheimt öryggisafrits. Hér er það notað wal-e til að draga út WAL hluti (restore_command) úr skjalasafninu og breytingarnar verða beittar eftir átta klukkustundir (recovery_min_apply_delay). Eftirmyndin mun fylgjast með breytingum á tímalínu í skjalasafninu, til dæmis vegna þyrpingarbilunar (recovery_target_timeline).

С recovery_min_apply_delay Þú getur sett upp straumafritun með töf, en það eru nokkrar gildrur hér sem tengjast afritunarlotum, heitri biðstöðu og svo framvegis. WAL skjalasafnið gerir þér kleift að forðast þau.

Viðfang recovery_min_apply_delay birtist aðeins í PostgreSQL 9.3. Í fyrri útgáfum þarftu að stilla samsetninguna fyrir frestað afritun batastjórnunaraðgerðir (pg_xlog_replay_pause(), pg_xlog_replay_resume()) eða geymdu WAL hluta í skjalasafni meðan á töfinni stendur.

Hvernig gerir PostgreSQL þetta?

Það er áhugavert að sjá hvernig PostgreSQL útfærir latan bata. Við skulum skoða recoveryApplyDelay(XlogReaderState). Það er kallað frá aðal endurtekningarlykkja fyrir hverja færslu frá 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;
}

Niðurstaðan er sú að seinkunin byggist á líkamlegum tíma sem skráður er í tímastimpli viðskiptaskuldbindingarinnar (xtime). Eins og þú sérð á seinkunin aðeins við um skuldbindingar og hefur ekki áhrif á aðrar færslur - allar breytingar eru beittar beint og skuldbindingunni er seinkað, þannig að við munum aðeins sjá breytingarnar eftir stilltu seinkunina.

Hvernig á að nota seinkaða eftirmynd til að endurheimta gögn

Segjum að við höfum gagnagrunnsklasa og eftirmynd með átta tíma seinkun á framleiðslu. Við skulum sjá hvernig á að endurheimta gögn með því að nota dæmi eyðir flýtileiðum óvart.

Þegar við lærðum um vandamálið, þá Hlé hefur verið gert á endurheimt skjalasafns fyrir frestað eftirmynd:

SELECT pg_xlog_replay_pause();

Með hléi áttum við enga hættu á að eftirmyndin myndi endurtaka beiðnina DELETE. Gagnlegur hlutur ef þú þarft tíma til að átta þig á öllu.

Málið er að frestað eftirmynd verður að ná augnablikinu fyrir beiðnina DELETE. Við vissum um það bil líkamlegan tíma fjarlægingar. Við höfum eytt recovery_min_apply_delay og bætti við recovery_target_time в recovery.conf. Svona nær eftirmyndin rétta augnablikinu án tafar:

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

Með tímastimplum er betra að minnka umframmagnið til að missa ekki af. Að vísu töpum við meiri gögnum eftir því sem lækkunin er meiri. Aftur, ef við missum af beiðninni DELETE, öllu verður eytt aftur og þú verður að byrja upp á nýtt (eða jafnvel taka kalt öryggisafrit fyrir PITR).

Við endurræstum frestað Postgres tilvikið og WAL hlutarnir voru endurteknir þar til tilgreindur tími var til staðar. Þú getur fylgst með framförum á þessu stigi með því að spyrja:

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;

Ef tímastimpillinn breytist ekki lengur er endurheimtunni lokið. Aðgerð er hægt að aðlaga recovery_target_actiontil að loka, kynna eða gera hlé á tilvikinu eftir að hafa reynt aftur (það er sjálfgefið lokað).

Gagnagrunnurinn kom aftur í ástand sitt fyrir þá óheppilegu beiðni. Nú geturðu til dæmis flutt út gögn. Við fluttum út eydd merkimiðagögn og alla tengla á málefni og sameiningarbeiðnir og færðum þau inn í framleiðslugagnagrunninn. Ef tapið er umfangsmikið geturðu einfaldlega kynnt eftirmyndina og notað hana sem aðal. En þá tapast allar breytingar eftir þann punkt sem við höfum náð okkur á.

Í stað tímastimpla er betra að nota viðskiptaauðkenni. Það er gagnlegt að skrá þessi auðkenni, til dæmis fyrir DDL yfirlýsingar (svo sem DROP TABLE), með því að nota log_statements = 'ddl'. Ef við værum með viðskiptaauðkenni myndum við taka recovery_target_xid og hljóp allt niður í viðskiptin fyrir beiðnina DELETE.

Að komast aftur til vinnu er mjög einfalt: fjarlægðu allar breytingar frá recovery.conf og endurræstu Postgres. Eftirmyndin mun brátt hafa átta klukkustunda töf aftur og við erum tilbúin fyrir framtíðarvandræði.

Bati ávinningur

Með frestað eftirmynd í stað köldu öryggisafrits þarftu ekki að eyða tíma í að endurheimta alla myndina úr skjalasafninu. Til dæmis tekur það okkur fimm klukkustundir að fá allt grunn 2 TB öryggisafritið. Og þá þarftu samt að nota allan daglegan WAL til að jafna þig í æskilegt ástand (í versta falli).

Frestað eftirmynd er betri en kalt öryggisafrit á tvo vegu:

  1. Það er engin þörf á að fjarlægja allt grunnafritið úr skjalasafninu.
  2. Það er fastur átta klukkustunda gluggi yfir WAL hluta sem þarf að endurtaka.

Við athugum líka stöðugt hvort hægt sé að búa til PITR frá WAL og við myndum fljótt taka eftir spillingu eða öðrum vandamálum með WAL skjalasafnið með því að fylgjast með seinkun frestaðrar eftirmyndar.

Í þessu dæmi tók það okkur 50 mínútur að endurheimta, sem þýðir að hraðinn var 110 GB af WAL gögnum á klukkustund (skjalasafnið var enn á AWS S3). Alls leystum við vandamálið og endurheimtum gögnin á 1,5 klukkustund.

Niðurstöður: þar sem frestað eftirmynd er gagnleg (og þar sem hún er ekki)

Notaðu seinkaða afritun sem skyndihjálp ef þú tapaðir óvart gögnum og tókst eftir þessu vandamáli innan stilltri seinkun.

En hafðu í huga: afritun er ekki öryggisafrit.

Afritun og afritun hafa mismunandi tilgang. Kalt öryggisafrit mun koma sér vel ef þú gerðir óvart DELETE eða DROP TABLE. Við gerum öryggisafrit úr frystigeymslu og endurheimtum fyrri stöðu töflunnar eða allan gagnagrunninn. En um leið beiðnin DROP TABLE er nánast samstundis afritað í öllum eftirmyndum á vinnuklasanum, svo venjuleg afritun mun ekki hjálpa hér. Afritunin sjálf heldur gagnagrunninum tiltækum þegar einstakir netþjónar eru leigðir út og dreifir álaginu.

Jafnvel með frestað eftirmynd, þurfum við stundum virkilega kalt öryggisafrit á öruggum stað ef bilun í gagnaveri, falinn skemmdur eða aðrir atburðir sem eru ekki áberandi strax. Afritun ein og sér er ekkert gagn hér.

Athugið. Á GitLab.com Sem stendur verjum við aðeins gegn gagnatapi á kerfisstigi og endurheimtum ekki gögn á notendastigi.

Heimild: www.habr.com

Bæta við athugasemd