Kepiye Gunakake Replikasi Lazy kanggo Disaster Recovery karo PostgreSQL

Kepiye Gunakake Replikasi Lazy kanggo Disaster Recovery karo PostgreSQL
Replikasi ora serep. Utawa ora? Mangkene carane nggunakake replikasi sing ditundha kanggo pulih saka trabasan sing ora disengaja.

Spesialis Infrastruktur GitLab tanggung jawab kanggo karya kasebut GitLab.com - conto GitLab paling gedhe ing alam. Kanthi 3 yuta pangguna lan meh 7 yuta proyek, iki minangka salah sawijining situs SaaS sumber terbuka paling gedhe kanthi arsitektur khusus. Tanpa sistem database PostgreSQL, infrastruktur GitLab.com ora bakal adoh, lan apa sing ditindakake kanggo njamin toleransi kesalahan yen ana kegagalan nalika data bisa ilang. Ora mungkin bencana kasebut bakal kelakon, nanging kita wis siyap kanthi apik lan nyedhiyakake macem-macem mekanisme serep lan replikasi.

Replikasi dudu sarana kanggo nggawe serep database (ndeleng ngisor iki). Nanging saiki kita bakal weruh carane cepet waras data sengaja dibusak nggunakake rΓ©plikasi puguh: on GitLab.com pangguna mbusak trabasan kanggo proyek gitlab-ce lan ilang sambungan karo nggabung panjalukan lan tugas.

Kanthi replika sing ditundha, kita mbalekake data mung 1,5 jam. Delengen kepiye kedadeyane.

Titik ing wektu Recovery karo PostgreSQL

PostgreSQL nduweni fungsi sing dibangun kanggo mulihake kahanan database menyang titik wektu tartamtu. Iku diarani Point-in-Wektu Recovery (PITR) lan nggunakake mekanisme sing padha supaya replika tetep gaul: miwiti karo gambar asli seko dipercaya saka kabeh kluster database (base backup), kita aplikasi seri saka owah-owahan negara nganti titik tartamtu ing wektu.

Kanggo nggunakake fitur iki kanggo serep kadhemen, kita ajeg nggawe serep basis data dhasar lan nyimpen ing arsip (GitLab arsip manggon ing panyimpenan maya Google). Kita uga ngawasi owah-owahan ing negara database kanthi arsip log nulis-ahead (nulis-ahead log, WAL). Lan kanthi kabeh iki, kita bisa nindakake PITR kanggo pemulihan bencana: diwiwiti kanthi gambar sing dijupuk sadurunge gagal, lan ngetrapake owah-owahan saka arsip WAL nganti gagal.

Apa replikasi sing ditundha?

Lazy replikasi yaiku aplikasi owah-owahan saka WAL kanthi wektu tundha. Tegese, transaksi kasebut kedadeyan sajrone jam X, nanging bakal katon ing tiron karo wektu tundha d ing jam X + d.

PostgreSQL duwe 2 cara kanggo nyiyapake replika database fisik: pemulihan serep lan replikasi streaming. Mulihake saka arsip, Intine kerjane kaya PITR, nanging terus-terusan: kita terus-terusan njupuk owah-owahan saka arsip WAL lan ditrapake menyang replika. A replikasi streaming langsung njupuk stream WAL saka host database hulu. Kita luwih seneng mbalekake arsip - luwih gampang ngatur lan nduweni kinerja normal sing tetep karo kluster produksi.

Carane nyiyapake Recovery telat saka arsip

Pilihan Recovery diterangake ing file recovery.conf. Tuladha:

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'

Kanthi paramèter kasebut, kita ngatur replika sing ditundha kanthi pemulihan serep. Ing kene digunakake wal-e kanggo ngekstrak segmen WAL (restore_command) saka arsip, lan owah-owahan bakal ditrapake sawise wolung jam (recovery_min_apply_delay). Replika bakal nonton owah-owahan timeline ing arsip, contone amarga failover kluster (recovery_target_timeline).

Π‘ recovery_min_apply_delay Sampeyan bisa nyiyapake replikasi streaming kanthi wektu tundha, nanging ana sawetara pitfalls ing kene sing ana hubungane karo slot replikasi, umpan balik siyaga panas, lan liya-liyane. Arsip WAL ngidini sampeyan nyingkiri.

Parameter recovery_min_apply_delay mung katon ing PostgreSQL 9.3. Ing versi sadurunge, kanggo replikasi ditundha sampeyan kudu ngatur kombinasi fungsi manajemen pemulihan (pg_xlog_replay_pause(), pg_xlog_replay_resume()) utawa tahan segmen WAL ing arsip sajrone wektu tundha.

Kepiye PostgreSQL nindakake iki?

Iku menarik kanggo ndeleng carane PostgreSQL ngleksanakake Recovery puguh. Ayo kang katon ing recoveryApplyDelay(XlogReaderState). Iki diarani saka loop pengulangan utama kanggo saben entri saka 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;
}

Intine yaiku wektu tundha adhedhasar wektu fisik sing dicathet ing cap wektu transaksi (xtime). Nalika sampeyan bisa ndeleng, wektu tundha mung ditrapake kanggo commits lan ora mengaruhi entri liyane - kabeh owah-owahan ditrapake langsung, lan commit wis telat, supaya kita mung bakal weruh owah-owahan sawise wektu tundha diatur.

Carane nggunakake replika telat kanggo mulihake data

Ayo kita duwe kluster database lan replika kanthi wektu tundha wolung jam ing produksi. Ayo ndeleng carane waras data nggunakake conto ora sengaja mbusak trabasan.

Nalika kita sinau babagan masalah kasebut, kita mulihake saka arsip wis dilereni soko tugas kanggo replika sing ditundha:

SELECT pg_xlog_replay_pause();

Kanthi ngaso, kita ora duwe risiko yen replika bakal mbaleni panjaluk kasebut DELETE. Bab sing migunani yen sampeyan butuh wektu kanggo ngerteni kabeh.

Intine yaiku replika sing ditundha kudu tekan wayahe sadurunge panjaluk DELETE. Kita kira-kira ngerti wektu mbusak fisik. Kita wis dibusak recovery_min_apply_delay lan ditambahake recovery_target_time Π² recovery.conf. Mangkene carane replika tekan wektu sing tepat tanpa wektu tundha:

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

Kanthi prangko wektu, luwih becik nyuda keluwihan supaya ora kantun. Bener, luwih akeh nyuda, luwih akeh data sing ilang. Maneh, yen kita kantun panjaluk DELETE, kabeh bakal dibusak maneh lan sampeyan kudu miwiti maneh (utawa malah njupuk serep kadhemen kanggo PITR).

Kita miwiti maneh conto Postgres sing ditundha lan segmen WAL diulang nganti wektu sing ditemtokake. Sampeyan bisa nglacak kemajuan ing tahap iki kanthi takon:

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;

Yen stempel wektu ora diganti maneh, pemulihan wis rampung. Tumindak bisa disesuaikan recovery_target_actionkanggo nutup, ningkatakΓ©, utawa ngaso conto sawise nyoba maneh (ditundha minangka standar).

Basis data bali menyang negarane sadurunge panjaluk sing apes kasebut. Saiki sampeyan bisa, contone, ngekspor data. Kita ngekspor data label sing wis dibusak lan kabeh pranala menyang masalah lan nggabungake panjalukan lan dipindhah menyang database produksi. Yen kerugian gedhe-gedhe, sampeyan mung bisa promosi replika lan nggunakake minangka sing utama. Nanging kabeh owah-owahan sawise titik sing wis pulih bakal ilang.

Tinimbang cap wektu, luwih becik nggunakake ID transaksi. Iku migunani kanggo ngrekam ID iki, contone, kanggo statement DDL (kayata DROP TABLE), kanthi nggunakake log_statements = 'ddl'. Yen kita duwe ID transaksi, kita bakal njupuk recovery_target_xid lan mlayu kabeh mudhun kanggo transaksi sadurunge request DELETE.

Mbalik kerja gampang banget: mbusak kabeh owah-owahan saka recovery.conf lan miwiti maneh Postgres. Replika kasebut bakal ana wektu tundha wolung jam maneh, lan kita wis siyap kanggo masalah ing mangsa ngarep.

Keuntungan Recovery

Kanthi replika sing ditundha tinimbang serep sing adhem, sampeyan ora kudu nglampahi jam kanggo mulihake kabeh gambar saka arsip. Contone, kita butuh limang jam kanggo entuk kabeh serep 2 TB dhasar. Banjur sampeyan isih kudu ngetrapake kabeh WAL saben dina kanggo pulih menyang negara sing dikarepake (ing kasus sing paling awon).

Replika sing ditundha luwih apik tinimbang serep kadhemen kanthi rong cara:

  1. Ora perlu mbusak kabeh serep dhasar saka arsip.
  2. Ana jendhela wolung jam tetep segmen WAL sing kudu diulang.

Kita uga tansah mriksa kanggo ndeleng apa iku bisa kanggo nggawe PITR saka WAL, lan kita bakal cepet sok dong mirsani korupsi utawa masalah liyane karo arsip WAL dening ngawasi lag tiron tundha.

Ing conto iki, kita butuh 50 menit kanggo mulihake, tegese kacepetan 110 GB data WAL saben jam (arsip isih aktif. AWS S3). Secara total, kita ngrampungake masalah kasebut lan mbalekake data sajrone 1,5 jam.

Asil: ing ngendi replika sing ditundha migunani (lan ora ana)

Gunakake replikasi telat minangka sepindah yen sampeyan ora sengaja ilang data lan weruh masalah iki ing wektu tundha diatur.

Nanging elinga: replikasi dudu serep.

Gawe serep lan replikasi duwe tujuan sing beda. A serep kadhemen bakal teka ing Handy yen sengaja digawe DELETE utawa DROP TABLE. Kita nggawe serep saka panyimpenan kadhemen lan mulihake negara sadurunge meja utawa kabeh database. Nanging ing wektu sing padha panjaluk DROP TABLE meh langsung maleh ing kabeh replika ing kluster apa, supaya replikasi biasa ora bakal bantuan kene. Replikasi dhewe tetep database kasedhiya nalika server individu disewakake lan distributes mbukak.

Malah kanthi tiron sing ditundha, kadhangkala kita butuh serep sing adhem ing papan sing aman yen ana kegagalan pusat data, karusakan sing didhelikake, utawa kedadeyan liyane sing ora langsung katon. Replikasi mung ora ana gunane ing kene.

komentar. Ing GitLab.com Saiki kita mung nglindhungi mundhut data ing tingkat sistem lan ora mbalekake data ing tingkat pangguna.

Source: www.habr.com

Add a comment