Kumaha Kami Nganggo Réplikasi Puguh pikeun Pamulihan Bencana sareng PostgreSQL

Kumaha Kami Nganggo Réplikasi Puguh pikeun Pamulihan Bencana sareng PostgreSQL
Réplikasi teu cadangan. Atanapi henteu? Kieu kumaha kami nganggo réplikasi anu ditunda pikeun pulih tina ngahapus potong kompas anu teu kahaja.

Spesialis Infrastruktur GitLab tanggung jawab kana padamelan éta GitLab.com - conto GitLab panggedéna di alam. Kalayan 3 juta pangguna sareng ampir 7 juta proyék, éta mangrupikeun salah sahiji situs SaaS open source panggedéna sareng arsitéktur khusus. Tanpa sistem database PostgreSQL, infrastruktur GitLab.com moal jauh, sareng naon anu urang laksanakeun pikeun mastikeun kasabaran kasalahan upami aya gagal nalika data tiasa leungit. Henteu mungkin musibah sapertos kitu bakal kajantenan, tapi kami siap-siap sareng nyayogikeun sagala rupa mékanisme cadangan sareng réplikasi.

Réplikasi sanes sarana pikeun nyadangkeun basis data (tingali di handap). Tapi ayeuna urang bakal ningali kumaha gancang cageur data ngahapus ngahaja ngagunakeun réplikasi puguh: on GitLab.com pamaké éta ngahapus potong kompas pikeun proyék gitlab-ce tur leungit sambungan kalawan ngagabung requests jeung tugas.

Kalayan réplika anu ditunda, kami pulih data ngan ukur 1,5 jam. Tingali kumaha kajadianana.

Titik dina recovery waktos sareng PostgreSQL

PostgreSQL boga fungsi diwangun-di nu restores kaayaan database ka titik husus dina jangka waktu. Disebutna Pamulihan Point-in-Time (PITR) tur ngagunakeun mékanisme sarua nu tetep replica up to date: dimimitian ku snapshot dipercaya tina sakabéh klaster database (base backup), urang nerapkeun runtuyan parobahan kaayaan nepi ka titik nu tangtu dina jangka waktu.

Pikeun ngagunakeun fitur ieu pikeun cadangan tiis, urang rutin nyieun cadangan basis data dasar tur nyimpen eta dina arsip (GitLab arsip hirup di Panyimpen awan Google). Urang ogé ngawas parobahan dina kaayaan database ku arsip nulis-payun log (nulis-payun log, WAL). Sareng sadaya ieu di tempat, urang tiasa ngalakukeun PITR pikeun pamulihan bencana: dimimitian ku snapshot anu dicandak sateuacan gagal, sareng nerapkeun parobihan tina arsip WAL dugi ka gagalna.

Naon réplikasi ditunda?

Puguh réplikasi nyaéta aplikasi parobahan tina WAL kalawan reureuh. Hartina, transaksi lumangsung dina sajam X, tapi bakal muncul dina réplika kalayan reureuh d dina sajam X + d.

PostgreSQL gaduh 2 cara pikeun nyetél réplika database fisik: pamulihan cadangan sareng réplikasi streaming. Malikkeun tina arsip, dasarna jalan kawas PITR, tapi terus-terusan: urang terus nimba parobahan tina arsip WAL jeung nerapkeun ka replika. A réplikasi streaming langsung retrieves aliran WAL ti host database hulu. Kami langkung milih pamulihan arsip - langkung gampang ngatur sareng gaduh prestasi normal anu tetep sareng kluster produksi.

Kumaha nyetél pamulihan anu ditunda tina arsip

Pilihan Pamulihan dijelaskeun dina file recovery.conf... Conto:

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'

Kalayan parameter ieu, kami ngonpigurasikeun réplika anu ditunda sareng pamulihan cadangan. Di dieu dipaké wal-e pikeun nimba bagéan WAL (restore_command) ti arsip, sarta parobahan bakal diterapkeun sanggeus dalapan jam (recovery_min_apply_delay). Réplika bakal ningali parobahan timeline dina arsip, contona kusabab gagal klaster (recovery_target_timeline).

С recovery_min_apply_delay Anjeun tiasa nyetél réplikasi streaming kalayan reureuh, tapi aya sababaraha pitfalls di dieu anu aya hubunganana sareng slot réplikasi, eupan balik sayaga panas, sareng sajabana. Arsip WAL ngamungkinkeun anjeun pikeun nyingkahanana.

parameter recovery_min_apply_delay mucunghul ngan dina PostgreSQL 9.3. Dina versi saméméhna, pikeun réplikasi nunggak anjeun kudu ngonpigurasikeun kombinasi fungsi manajemén recovery (pg_xlog_replay_pause(), pg_xlog_replay_resume()) atawa tahan bagéan WAL dina arsip pikeun lilana reureuh.

Kumaha PostgreSQL ngalakukeun ieu?

Éta pikaresepeun pikeun ningali kumaha PostgreSQL ngalaksanakeun pamulihan anu puguh. Hayu urang tingali recoveryApplyDelay(XlogReaderState). Disebutna ti loop ulang utama pikeun tiap éntri ti 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;
}

Garis handapna nyaéta yén reureuh dumasar kana waktos fisik anu kacatet dina cap waktu transaksi komitmen (xtime). Sakumaha anjeun tiasa tingali, reureuh ngan lumaku pikeun commits sarta henteu mangaruhan éntri séjén - sagala parobahan diterapkeun langsung, sarta commit ditunda, ku kituna urang ngan bakal ningali parobahan sanggeus reureuh ngonpigurasi.

Kumaha ngagunakeun réplika anu ditunda pikeun mulangkeun data

Sebutkeun urang gaduh klaster database sareng réplika kalayan tunda dalapan jam dina produksi. Hayu urang tingali kumaha cageur data ngagunakeun conto teu kahaja ngahapus potong kompas.

Nalika urang diajar ngeunaan masalah, urang restorasi arsip geus direureuhkeun pikeun réplika nunda:

SELECT pg_xlog_replay_pause();

Kalayan jeda, urang henteu ngagaduhan résiko yén réplika bakal ngulang pamundut éta DELETE. Hiji hal anu mangpaat upami anjeun peryogi waktos pikeun terang sadayana.

Intina nyaéta réplika anu ditunda kedah ngahontal momen sateuacan pamundut DELETE. Urang kira-kira terang waktos panyabutan fisik. Kami geus dihapus recovery_min_apply_delay sarta ditambahkeun recovery_target_time в recovery.conf. Ieu kumaha réplika ngahontal momen anu pas tanpa reureuh:

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

Kalayan perangko waktos, langkung saé ngirangan kaleuwihan supados henteu sono. Leres, langkung ageung panurunan, langkung seueur data anu leungit. Sakali deui, upami urang sono kana pamundut DELETE, sadayana bakal dipupus deui sareng anjeun kedah ngamimitian deui (atanapi nyandak cadangan tiis pikeun PITR).

Urang ngamimitian deui conto Postgres anu ditunda sareng bagéan WAL diulang dugi ka waktos anu ditangtukeun. Anjeun tiasa ngalacak kamajuan dina tahap ieu ku naroskeun:

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;

Upami timestamp henteu robih deui, pamulihan parantos réngsé. Peta bisa ngaropéa recovery_target_actionpikeun nutup, ngamajukeun, atanapi ngareureuhkeun conto saatos cobian deui (ditunda sacara standar).

pangkalan data balik ka kaayaan na saméméh éta pamundut musibah. Ayeuna anjeun tiasa, contona, ékspor data. Kami ngékspor data labél anu dihapus sareng sadaya tautan kana masalah sareng ngahijikeun pamundut sareng ngalihkeun kana database produksi. Upami karugian ageung skala, anjeun ngan saukur tiasa ngamajukeun réplika sareng dianggo salaku anu utama. Tapi teras sadaya parobihan saatos titik anu kami pulih bakal leungit.

Gantina timestamps, eta leuwih hade migunakeun ID urus. Mangpaat pikeun ngarékam ID ieu, contona, pikeun pernyataan DDL (sapertos DROP TABLE), ku ngagunakeun log_statements = 'ddl'. Lamun urang boga ID urus, urang bakal nyandak recovery_target_xid tur lumpat sagalana ka handap pikeun urus saméméh pamundut DELETE.

Balik deui ka padamelan saderhana pisan: hapus sadaya parobihan recovery.conf sareng balikan deui Postgres. Réplika éta engké bakal ditunda deui dalapan jam, sareng kami siap pikeun masalah anu bakal datang.

Mangpaat Pamulihan

Kalawan replika nunggak tinimbang cadangan tiis, anjeun teu kudu méakkeun jam mulangkeun sakabéh gambar tina arsip. Contona, urang butuh lima jam pikeun meunangkeun sakabéh cadangan dasar 2 TB. Lajeng anjeun masih kudu nerapkeun sakabéh WAL poean cageur ka kaayaan nu dipikahoyong (dina kasus awon).

Réplika anu ditunda langkung saé tibatan cadangan tiis ku dua cara:

  1. Henteu kedah ngahapus sadaya cadangan dasar tina arsip.
  2. Aya jandela tetep dalapan jam tina bagéan WAL anu kudu diulang.

Urang ogé terus pariksa ningali lamun kasebut nyaéta dimungkinkeun pikeun nyieun hiji PITR ti WAL, sarta kami bakal gancang perhatikeun korupsi atawa masalah sejenna jeung arsip WAL ku mantau lag replica nunggak.

Dina conto ieu, urang butuh 50 menit pikeun mulangkeun, hartina lajuna 110 GB data WAL per jam (arsipna masih hurung. AWS S3). Dina total, urang direngsekeun masalah jeung pulih data dina 1,5 jam.

Hasil: dimana réplika anu ditunda mangpaat (sareng henteu)

Anggo réplikasi anu ditunda salaku bantosan heula upami anjeun ngahaja kaleungitan data sareng ningali masalah ieu dina waktos reureuh anu dikonpigurasikeun.

Tapi émut: réplikasi sanés cadangan.

Nyadangkeun sareng réplikasi gaduh tujuan anu béda. A cadangan tiis bakal datang dina gunana lamun ngahaja dijieun DELETE atawa DROP TABLE. Urang nyieun cadangan ti gudang tiis tur malikkeun kaayaan saméméhna tina tabel atawa sakabéh database. Tapi dina waktos anu sareng pamundut DROP TABLE ampir instan dihasilkeun dina sakabéh réplika dina klaster gawé, jadi réplikasi biasa moal mantuan di dieu. Réplikasi sorangan ngajaga database sadia nalika server individu anu disewa kaluar sarta distributes beban.

Malah ku réplika nu ditunda, urang kadang bener perlu cadangan tiis di tempat anu aman lamun gagalna puseur data, karuksakan disumputkeun, atawa acara séjén anu teu langsung noticeable lumangsung. Réplikasi nyalira henteu aya gunana di dieu.

nyarios. Asupkeun GitLab.com Urang ayeuna ngan ngajaga ngalawan leungitna data dina tingkat sistem jeung teu cageur data dina tingkat pamaké.

sumber: www.habr.com

Tambahkeun komentar