Si e përdorëm replikimin dembel për rikuperimin nga fatkeqësitë me PostgreSQL

Si e përdorëm replikimin dembel për rikuperimin nga fatkeqësitë me PostgreSQL
Replikimi nuk është rezervë. Ose jo? Ja se si kemi përdorur replikimin e shtyrë për t'u rikuperuar nga fshirja aksidentale e shkurtoreve.

Specialistët e infrastrukturës GitLab është përgjegjës për punën GitLab.com - shembulli më i madh GitLab në natyrë. Me 3 milion përdorues dhe afro 7 milion projekte, është një nga faqet më të mëdha të SaaS me burim të hapur me një arkitekturë të dedikuar. Pa sistemin e bazës së të dhënave PostgreSQL, infrastruktura GitLab.com nuk do të shkojë larg dhe çfarë po bëjmë ne për të siguruar tolerancën e gabimeve në rast të ndonjë dështimi kur të dhënat mund të humbasin. Nuk ka gjasa që të ndodhë një fatkeqësi e tillë, por ne jemi të përgatitur mirë dhe të pajisur me mekanizma të ndryshëm rezervë dhe riprodhimi.

Replikimi nuk është një mjet për të mbështetur bazat e të dhënave (shiko më poshtë). Por tani do të shohim se si të rikuperojmë shpejt të dhënat e fshira aksidentalisht duke përdorur replikimin dembel: aktiv GitLab.com përdoruesit fshiu shkurtoren për projektin gitlab-ce dhe lidhjet e humbura me kërkesat dhe detyrat për bashkim.

Me një kopje të shtyrë, ne rikuperuam të dhënat në vetëm 1,5 orë. Shikoni si ndodhi.

Pika në rikuperimin e kohës me PostgreSQL

PostgreSQL ka një funksion të integruar që rikthen gjendjen e bazës së të dhënave në një moment të caktuar kohor. Quhet Rimëkëmbja në kohë (PITR) dhe përdor të njëjtat mekanizma që e mbajnë të përditësuar kopjen: duke filluar me një fotografi të besueshme të të gjithë grupit të bazës së të dhënave (backup bazë), ne aplikojmë një seri ndryshimesh të gjendjes deri në një moment të caktuar kohor.

Për të përdorur këtë veçori për kopje rezervë të ftohtë, ne bëjmë rregullisht një kopje rezervë bazë të bazës së të dhënave dhe e ruajmë atë në një arkiv (arkivat GitLab jetojnë në Ruajtja në renë kompjuterike të Google). Ne gjithashtu monitorojmë ndryshimet në gjendjen e bazës së të dhënave duke arkivuar regjistrin e shkrimit përpara (regjistri i parashkrimit, WAL). Dhe me gjithë këtë në vend, ne mund të bëjmë një PITR për rikuperimin nga fatkeqësitë: duke filluar me fotografinë e marrë përpara dështimit dhe duke aplikuar ndryshimet nga arkivi WAL deri te dështimi.

Çfarë është replikimi i shtyrë?

Replikimi dembel është aplikimi i ndryshimeve nga WAL me vonesë. Kjo do të thotë, transaksioni ndodhi brenda një ore X, por do të shfaqet në kopje me vonesë d per nje ore X + d.

PostgreSQL ka 2 mënyra për të vendosur një kopje fizike të bazës së të dhënave: rikuperimi i rezervës dhe riprodhimi i transmetimit. Rivendosja nga një arkiv, në thelb funksionon si PITR, por vazhdimisht: ne i marrim vazhdimisht ndryshimet nga arkivi WAL dhe i zbatojmë ato në kopje. A riprodhimi i transmetimit merr drejtpërdrejt rrymën WAL nga hosti i bazës së të dhënave në rrjedhën e sipërme. Ne preferojmë rikuperimin e arkivit - është më i lehtë për t'u menaxhuar dhe ka performancë normale që shkon në hap me grupin e prodhimit.

Si të vendosni rikuperimin e vonuar nga një arkiv

Opsionet e rikuperimit përshkruar në dosje recovery.conf. Shembull:

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 këto parametra, ne konfiguruam një kopje të shtyrë me rikuperim rezervë. Këtu përdoret wal-e për nxjerrjen e segmenteve WAL (restore_command) nga arkivi dhe ndryshimet do të aplikohen pas tetë orësh (recovery_min_apply_delay). Replika do të shikojë për ndryshimet e afatit kohor në arkiv, për shembull për shkak të një dështimi të grupit (recovery_target_timeline).

С recovery_min_apply_delay Ju mund të konfiguroni riprodhimin e transmetimit me vonesë, por këtu ka disa gracka që lidhen me lojërat e riprodhimit, reagimet e nxehta të gatishmërisë, etj. Arkivi WAL ju lejon t'i shmangni ato.

Parametër recovery_min_apply_delay u shfaq vetëm në PostgreSQL 9.3. Në versionet e mëparshme, për përsëritjen e shtyrë duhet të konfiguroni kombinimin funksionet e menaxhimit të rimëkëmbjes (pg_xlog_replay_pause(), pg_xlog_replay_resume()) ose mbani segmentet WAL në arkiv për kohëzgjatjen e vonesës.

Si e bën këtë PostgreSQL?

Është interesante të shihet se si PostgreSQL zbaton rimëkëmbjen dembel. Le të shohim recoveryApplyDelay(XlogReaderState). Është thirrur nga cikli kryesor i përsëritjes për çdo hyrje nga 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;
}

Në fund të fundit është se vonesa bazohet në kohën fizike të regjistruar në vulën kohore të kryerjes së transaksionit (xtime). Siç mund ta shihni, vonesa vlen vetëm për kryerjet dhe nuk ndikon në hyrjet e tjera - të gjitha ndryshimet zbatohen drejtpërdrejt, dhe kryerja vonohet, kështu që ne do t'i shohim ndryshimet vetëm pas vonesës së konfiguruar.

Si të përdorni një kopje të vonuar për të rivendosur të dhënat

Le të themi se kemi një grup të dhënash dhe një kopje me një vonesë tetë orë në prodhim. Le të shohim se si të rikuperojmë të dhënat duke përdorur një shembull fshirja aksidentale e shkurtoreve.

Kur mësuam për problemin, ne restaurimi i arkivit është ndërprerë për një kopje të shtyrë:

SELECT pg_xlog_replay_pause();

Me një pauzë, nuk kishim rrezik që kopja të përsëriste kërkesën DELETE. Një gjë e dobishme nëse keni nevojë për kohë për të kuptuar gjithçka.

Çështja është se kopja e shtyrë duhet të arrijë në momentin përpara kërkesës DELETE. Përafërsisht e dinim kohën fizike të largimit. Ne kemi fshirë recovery_min_apply_delay dhe shtoi recovery_target_time в recovery.conf. Ja se si kopja arrin momentin e duhur pa vonesë:

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

Me vulat kohore, është më mirë të zvogëloni tepricën për të mos humbur. Vërtetë, sa më e madhe të jetë rënia, aq më shumë të dhëna humbasim. Përsëri, nëse na mungon kërkesa DELETE, gjithçka do të fshihet përsëri dhe ju do të duhet të filloni nga e para (ose edhe të merrni një kopje rezervë të ftohtë për PITR).

Ne rifilluam shembullin e shtyrë të Postgres dhe segmentet WAL u përsëritën deri në kohën e caktuar. Ju mund të gjurmoni përparimin në këtë fazë duke pyetur:

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;

Nëse vula kohore nuk ndryshon më, rikuperimi përfundon. Veprimi mund të personalizohet recovery_target_actionpër të mbyllur, promovuar ose vendosur në pauzë shembullin pas riprovës (ai është pezulluar si parazgjedhje).

Baza e të dhënave u kthye në gjendjen e saj përpara asaj kërkese fatkeqe. Tani mund, për shembull, të eksportoni të dhëna. Ne eksportuam të dhënat e etiketës së fshirë dhe të gjitha lidhjet me problemet dhe kërkesat për bashkim dhe i zhvendosëm në bazën e të dhënave të prodhimit. Nëse humbjet janë në shkallë të gjerë, thjesht mund të promovoni kopjen dhe ta përdorni atë si kryesore. Por më pas të gjitha ndryshimet pas pikës në të cilën jemi rikuperuar do të humbasin.

Në vend të vulave kohore, është më mirë të përdorni ID-të e transaksionit. Është e dobishme të regjistrohen këto ID, për shembull, për deklaratat DDL (si p.sh DROP TABLE), duke përdorur log_statements = 'ddl'. Nëse do të kishim një ID transaksioni, do të merrnim recovery_target_xid dhe përfundoi gjithçka deri në transaksion përpara kërkesës DELETE.

Rikthimi në punë është shumë i thjeshtë: hiqni të gjitha ndryshimet nga recovery.conf dhe rinisni Postgres. Replika së shpejti do të ketë përsëri një vonesë tetë orëshe dhe ne jemi të përgatitur për problemet e ardhshme.

Përfitimet e Rimëkëmbjes

Me një kopje të shtyrë në vend të një kopje rezervë të ftohtë, nuk duhet të shpenzoni orë të tëra për të rivendosur të gjithë imazhin nga arkivi. Për shembull, na duhen pesë orë për të marrë të gjithë rezervën bazë prej 2 TB. Dhe pastaj duhet të aplikoni të gjithë WAL-in ditor për t'u rikuperuar në gjendjen e dëshiruar (në rastin më të keq).

Një kopje e shtyrë është më e mirë se një kopje rezervë e ftohtë në dy mënyra:

  1. Nuk ka nevojë të hiqni të gjithë rezervën bazë nga arkivi.
  2. Ekziston një dritare fikse tetë-orëshe e segmenteve WAL që duhet të përsëriten.

Ne gjithashtu kontrollojmë vazhdimisht për të parë nëse është e mundur të bëjmë një PITR nga WAL dhe do të vërejmë shpejt korrupsion ose probleme të tjera me arkivin WAL duke monitoruar vonesën e kopjes së shtyrë.

Në këtë shembull, na u deshën 50 minuta për të rivendosur, që do të thotë se shpejtësia ishte 110 GB të dhëna WAL në orë (arkivi ishte ende aktiv AWS S3). Në total, ne e zgjidhëm problemin dhe i rikuperuam të dhënat në 1,5 orë.

Rezultatet: ku një kopje e shtyrë është e dobishme (dhe ku nuk është)

Përdorni riprodhimin e vonuar si ndihmë të parë nëse keni humbur aksidentalisht të dhënat dhe e keni vënë re këtë problem brenda vonesës së konfiguruar.

Por mbani në mend: përsëritja nuk është një kopje rezervë.

Rezervimi dhe përsëritja kanë qëllime të ndryshme. Një kopje rezervë e ftohtë do të jetë e dobishme nëse e keni bërë aksidentalisht DELETE ose DROP TABLE. Ne bëjmë një kopje rezervë nga ruajtja e ftohtë dhe rivendosim gjendjen e mëparshme të tabelës ose të gjithë bazës së të dhënave. Por në të njëjtën kohë edhe kërkesa DROP TABLE riprodhohet pothuajse menjëherë në të gjitha kopjet në grupin e punës, kështu që përsëritja e zakonshme nuk do të ndihmojë këtu. Vetë replikimi e mban të disponueshme bazën e të dhënave kur jepen me qira serverë individualë dhe shpërndan ngarkesën.

Edhe me një kopje të shtyrë, ndonjëherë na duhet vërtet një kopje rezervë e ftohtë në një vend të sigurt nëse ndodh një dështim i qendrës së të dhënave, dëmtim i fshehur ose ngjarje të tjera që nuk janë të dukshme menjëherë. Vetëm replikimi nuk ka dobi këtu.

Shënim. në GitLab.com Aktualisht ne mbrojmë vetëm nga humbja e të dhënave në nivel sistemi dhe nuk i rikuperojmë të dhënat në nivelin e përdoruesit.

Burimi: www.habr.com

Shto një koment