Nola erabili genuen Lazy Replication Hondamendiak berreskuratzeko PostgreSQL-rekin

Nola erabili genuen Lazy Replication Hondamendiak berreskuratzeko PostgreSQL-rekin
Erreplikatzea ez da babeskopia. Edo ez? Hona hemen nola erabili genuen erreplikazio alferra berreskuratzeko lasterbideak nahi gabe ezabatuz.

azpiegituren espezialistak GitLab da lanaren arduraduna GitLab.com - Naturako GitLab-en instantziarik handiena. 3 milioi erabiltzaile eta ia 7 milioi proiekturekin, kode irekiko SaaS gune handienetako bat da, arkitektura dedikatu batekin. PostgreSQL datu-base sistemarik gabe, GitLab.com azpiegitura ez da urrutira joango, eta guk egiten ez duguna akatsen tolerantziarako hutsegiteen kasuan, datuak gal ditzakezunean. Nekez gertatuko da halako hondamendirik, baina ondo prestatu eta hornitu genuen hainbat babeskopia eta erreplika mekanismoekin.

Erreplikatzea ez da zure datu-basearen babeskopia tresna (ikusi behean). Baina orain ustekabean ezabatutako datuak nola azkar berreskuratu ikusiko dugu erreplikazio alferra erabiliz: aktibatuta GitLab.com erabiltzaileak kendu lasterbidea proiekturako gitlab-ce eta konexioak galdu ziren bateratze-eskaerekin eta zereginekin.

Erreplika atzeratuarekin, 1,5 ordutan berreskuratu ditugu datuak. Ikusi nola zegoen.

Une-denboran berreskuratzea PostgreSQL-rekin

PostgreSQL-k datu-base baten egoera une jakin batera berrezartzen duen funtzio integratua du. Deitzen da Puntu-denbora berreskuratzea (PITR) eta erreplika eguneratuta mantentzen duten mekanismo berberak erabiltzen ditu: datu-baseen kluster osoaren argazki fidagarri batetik abiatuta (oinarrizko babeskopia), egoera-aldaketa batzuk aplikatzen ditugu une jakin batera arte.

Ezaugarri hau babeskopia hotz baterako erabiltzeko, aldian-aldian oinarrizko datu-basearen babeskopia bat egiten dugu eta artxibo batean gordetzen dugu (GitLab artxiboak bizi dira. Google hodeiko biltegiratzea). Datu-basearen egoera-aldaketak ere kontrolatzen ditugu idazketa-aurreko erregistro bat artxibatuz (idatzi aurretik erregistroa, WAL). Eta honekin guztiarekin, hondamendiak berreskuratzeko PITR egin dezakegu: errorea baino lehen ateratako argazki batekin hasten gara eta WAL artxibotik kraskadura arte aplikatuko ditugu aldaketak.

Zer da atzeratutako erreplikazioa?

Erreplikazio atzeratua WAL-tik aldaketak atzerapenarekin aplikatzea da. Hau da, transakzioa orduan gertatu zen X, baina erreplikan atzerapenarekin agertuko da d ordu batean X + d.

PostgreSQL-n datu-base fisikoaren erreplika bat konfiguratzeko 2 modu daude: artxiboaren leheneratzea eta streaming erreplikazioa. Artxibo batetik leheneratzea, funtsean PITR bezala funtzionatzen du, baina etengabe: etengabe ari gara WAL artxibotik aldaketak ateratzen eta erreplikan aplikatzen. A streaming erreplikazioa WAL korrontea zuzenean lortzen du gorako datu-basearen ostalaritik. Artxibo batetik berrezartzea nahiago dugu; kudeatzeko errazagoa da eta errendimendu normala du, ekoizpen-kluster baten atzean geratzen ez dena.

Nola konfiguratu atzeratutako babeskopia berreskuratzea

Berreskuratzeko aukerak fitxategian deskribatuta recovery.conf... Adibidea:

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'

Ezarpen hauekin, atzeratutako erreplika bat konfiguratu dugu artxiboaren leheneratzearekin. Hemen erabiltzen da wal-e WAL segmentuak ateratzeko (restore_command) artxibotik, eta aldaketak zortzi orduren buruan aplikatuko dira (recovery_min_apply_delay). Erreplikak artxiboan denbora-lerroko aldaketak ikusiko ditu, adibidez, kluster hutsegite baten ondorioz (recovery_target_timeline).

Π‘ recovery_min_apply_delay latentzia-streaming-eko erreplikazioa konfigura dezakezu, baina erreplikazio-zirrikituekin, ordezko bero-erantzunarekin eta abarrekin lotutako hutsune pare bat daude. WAL artxiboak saihesten ditu.

Parametroa recovery_min_apply_delay PostgreSQL 9.3-n bakarrik agertu zen. Aurreko bertsioetan, atzeratutako erreplikazioak konbinazioa behar du berreskurapena kudeatzeko funtzioak (pg_xlog_replay_pause(), pg_xlog_replay_resume()) edo eduki WAL segmentuak artxiboan atzerapenak irauten duen bitartean.

Nola egiten du PostgreSQL-k?

Interesgarria da PostgreSQL-k nola inplementatzen duen leheneratzea alferra. Ikus dezagun recoveryApplyDelay(XlogReaderState). Deitzen zaio begizta nagusia errepikatu WALeko sarrera bakoitzeko.

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

Beheko lerroa da atzerapena transakzio-konpromisoaren denbora-zigiluan erregistratutako denbora fisikoan oinarritzen dela (xtime). Ikus dezakezunez, atzerapena konpromezuei bakarrik aplikatzen zaie eta ez die beste erregistroei eragiten; aldaketa guztiak zuzenean aplikatzen dira eta konpromisoa atzeratu egiten da, beraz, konfiguratutako atzerapenaren ondoren bakarrik ikusiko ditugu aldaketak.

Nola erabili erreplika alferra datuak berreskuratzeko

Demagun produkzioan datu-base kluster bat eta zortzi orduko atzerapenarekin erreplika bat dugula. Ikus dezagun nola berreskuratu datuak adibide bat erabiliz lasterbideak ustekabean ezabatzea.

Arazoaz jabetu ginenean, guk babeskopien berreskurapena pausatu du atzeratutako errepliketarako:

SELECT pg_xlog_replay_pause();

Etenaldi batekin, ez genuen erreplikak eskaera errepikatzeko arriskurik izan DELETE. Gauza erabilgarria dena argitzeko denbora behar baduzu.

Beheko lerroa da atzeratutako erreplika eskaeraren aurreko momentura iritsi behar dela DELETE. Gutxi gorabehera ezagutzen genuen kentzeko denbora fisikoa. Kendu genuen recovery_min_apply_delay eta gehitu recovery_target_time Π² recovery.conf. Beraz, erreplika une egokira iristen da atzerapenik gabe:

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

Denbora-zigiluekin, hobe da soberakina murriztea, ez galtzeko. Egia da, zenbat eta txikiagoa izan, orduan eta datu gehiago galtzen ditugu. Berriz ere, eskaera saltatzen badugu DELETE, dena berriro ezabatuko da eta berriro hasi beharko duzu (edo PITRrako babeskopia hotz bat ere hartu).

Atzeratutako Postgres instantzia berrabiarazi genuen eta WAL segmentuak zehaztutako ordura arte errepikatu ziren. Fase honetan aurrerapena jarrai dezakezu kontsulta eginez:

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;

Denbora-zigilua aldatzen ez bada, leheneratzea osatu da. Ekintza pertsonaliza dezakezu recovery_target_actioninstantzia ixteko, sustatzeko edo eteteko berriro saiatu ondoren (lehenespenez pausatzen da).

Datu-basea estatura iritsi zen eskaera gaizto horren aurretik. Orain, adibidez, datuak esportatu ditzakezu. Urruneko etiketa-datuak eta gaietarako eta bateratze-eskaeretarako esteka guztiak esportatu ditugu eta ekoizpen datu-basera transferitu ditugu. Galerak handiak badira, erreplika sustatu eta nagusi gisa erabil dezakezu. Baina gero aldaketa guztiak galduko dira berreskuratu genuen momentuaren ondoren.

Hobe da transakzioen IDak denbora-zigiluen ordez erabiltzea. Baliagarria da ID hauek grabatzea, adibidez, DDL adierazpenetarako (adibidez DROP TABLE), erabiliz log_statements = 'ddl'. Transakzio ID bat izango bagenu, hartuko genuke recovery_target_xid eta eskaera egin baino lehen transakziora eraman zuen guztia DELETE.

Lanera itzultzea oso erraza da: kendu aldaketa guztiak recovery.conf eta berrabiarazi postgres. Laster kueak berriro zortzi orduko atzerapena izango du, eta prest gaude etorkizuneko arazoetarako.

Berreskuratze-prestazioak

Atzeratutako erreplika batekin, babeskopia hotz baten ordez, ez duzu ordurik eman behar artxiboko argazki osoa leheneratzen. Esate baterako, bost ordu behar ditugu 2 TBko oinarrizko babeskopia osoa lortzeko. Eta gero, oraindik ere eguneroko WAL osoa aplikatu behar duzu nahi duzun egoerara berreskuratzeko (kasurik txarrenean).

Atzeratutako erreplika bat babeskopia hotza baino hobea da bi modutan:

  1. Ez duzu artxibotik oinarrizko babeskopia osoa eskuratu beharrik.
  2. Errepikatu behar den WAL segmentuen zortzi orduko leiho finko bat dago.

Gainera, WAL PITR egin daitekeen ala ez egiaztatzen ari gara etengabe, eta WAL artxiboaren ustelkeria edo bestelako arazoak azkar antzemango genituzke atzeratutako erreplikaren atzerapena kontrolatuz.

Adibide honetan, 50 minutu behar izan ditugu leheneratzeko, hau da, abiadura orduko 110 GB WAL datu zen (artxiboa oraindik martxan zegoen AWS S3). Guztira, arazoa konpondu dugu eta 1,5 ordutan datuak berreskuratu ditugu.

Laburpena: atzeratutako erreplika non erabilgarria den (eta non ez)

Erabili atzeratutako erreplikazioa lehen laguntza gisa, ustekabean datuak galtzen badituzu eta konfiguratutako atzerapenean hondamendia nabaritzen baduzu.

Baina kontuan izan: erreplikazioa ez da babeskopia.

Babeskopia eta erreplikazioak helburu desberdinak dituzte. Babeskopia hotza erabilgarria izango da ustekabean egin baduzu DELETE edo DROP TABLE. Hotz biltegitik babeskopia bat egiten dugu eta taula baten edo datu-base oso baten aurreko egoera berreskuratzen dugu. Baina aldi berean eskaera DROP TABLE ia berehala erreproduzitzen da lan-klusterreko erreplika guztietan, beraz, erreplikazio erregularrak ez du hemen gordeko. Erreplikak berak datu-basea eskuragarri mantentzen du banakako zerbitzariak alokatzen direnean eta karga banatzen duenean.

Nahiz eta atzeratutako erreplika bat izan, batzuetan segurtasun-kopia hotza behar dugu leku seguru batean, bat-batean datu-zentroko hutsegite bat, ezkutuko kalteak edo berehala nabaritzen ez dituzun bestelako gertaerak gertatzen badira. Hemen erreplika batetik ez dago zentzurik.

Kontuan izan. buruzko GitLab.com Gaur egun, sistema mailan datuak galtzearen aurka babesten ditugu eta ez ditugu erabiltzaileen mailan datuak leheneratzen.

Iturria: www.habr.com

Gehitu iruzkin berria