Jinsi Tulivyotumia Kurudia kwa Uvivu kwa Urejeshaji wa Maafa na PostgreSQL

Jinsi Tulivyotumia Kurudia kwa Uvivu kwa Urejeshaji wa Maafa na PostgreSQL
Urudufishaji sio nakala rudufu. Au siyo? Hivi ndivyo tulivyotumia urudufishaji ulioahirishwa ili kupata nafuu kutokana na kufuta njia za mkato kimakosa.

Wataalamu wa miundombinu GitLab inawajibika kwa kazi hiyo GitLab.com - mfano mkubwa zaidi wa GitLab katika asili. Ikiwa na watumiaji milioni 3 na karibu miradi milioni 7, ni mojawapo ya tovuti kubwa zaidi za chanzo huria za SaaS zilizo na usanifu maalum. Bila mfumo wa hifadhidata wa PostgreSQL, miundombinu ya GitLab.com haitafika mbali, na tunafanya nini ili kuhakikisha uvumilivu wa hitilafu endapo kutatokea hitilafu zozote wakati data inaweza kupotea. Haiwezekani kwamba maafa kama haya yatatokea, lakini tumejitayarisha vyema na tumejazwa na njia mbalimbali za kuhifadhi na kurudia.

Kuiga sio njia ya kuhifadhi hifadhidata (tazama hapa chini) Lakini sasa tutaona jinsi ya kurejesha haraka data iliyofutwa kwa bahati mbaya kwa kutumia replication ya uvivu: on GitLab.com user ilifuta njia ya mkato kwa mradi huo gitlab-ce na miunganisho iliyopotea na maombi ya kuunganisha na kazi.

Kwa nakala iliyoahirishwa, tulirejesha data kwa saa 1,5 pekee. Angalia jinsi ilivyotokea.

Onyesha urejeshaji wa wakati na PostgreSQL

PostgreSQL ina kitendakazi kilichojengewa ndani ambacho kinarejesha hali ya hifadhidata kwa uhakika maalum kwa wakati. Inaitwa Urejeshaji wa Muda-kwa-Muda (PITR) na hutumia njia zile zile zinazosasisha nakala: kuanzia na muhtasari wa kuaminika wa mkusanyiko mzima wa hifadhidata (chelezo msingi), tunaweka mfululizo wa mabadiliko ya hali hadi wakati fulani.

Ili kutumia kipengele hiki kuhifadhi nakala rudufu, mara kwa mara tunatengeneza hifadhidata ya msingi na kuihifadhi kwenye kumbukumbu (kumbukumbu za GitLab huishi ndani. Hifadhi ya wingu ya Google) Pia tunafuatilia mabadiliko katika hali ya hifadhidata kwa kuhifadhi kumbukumbu ya kuandika-mbele (andika-mbele logi, WAL). Na kwa haya yote mahali, tunaweza kufanya PITR kwa uokoaji wa maafa: kuanzia na picha iliyochukuliwa kabla ya kushindwa, na kutumia mabadiliko kutoka kwa kumbukumbu ya WAL hadi kushindwa.

Urudufu ulioahirishwa ni nini?

Urudiaji wa uvivu ni utumiaji wa mabadiliko kutoka kwa WAL kwa kucheleweshwa. Hiyo ni, shughuli ilifanyika kwa saa moja X, lakini itaonekana kwenye nakala kwa kuchelewa d kwa saa X + d.

PostgreSQL ina njia 2 za kusanidi nakala halisi ya hifadhidata: urejeshaji chelezo na urudufishaji wa utiririshaji. Inarejesha kutoka kwenye kumbukumbu, kimsingi hufanya kazi kama PITR, lakini mfululizo: sisi hurejesha mabadiliko kila mara kutoka kwenye kumbukumbu ya WAL na kuyatumia kwenye nakala. A urudufishaji wa utiririshaji hurejesha moja kwa moja mtiririko wa WAL kutoka kwa seva pangishi ya juu ya mkondo. Tunapendelea urejeshaji wa kumbukumbu - ni rahisi kudhibiti na ina utendaji wa kawaida unaoendana na kundi la uzalishaji.

Jinsi ya kusanidi urejeshaji uliocheleweshwa kutoka kwa kumbukumbu

Chaguzi za Urejeshaji ilivyoelezwa kwenye faili recovery.conf. Mfano:

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'

Kwa vigezo hivi, tulisanidi nakala iliyoahirishwa na uokoaji wa chelezo. Hapa inatumika wal-e kutoa sehemu za WAL (restore_command) kutoka kwenye kumbukumbu, na mabadiliko yatatumika baada ya saa nane (recovery_min_apply_delay) Replica itatazama mabadiliko ya kalenda ya matukio kwenye kumbukumbu, kwa mfano kwa sababu ya kushindwa kwa nguzo (recovery_target_timeline).

Π‘ recovery_min_apply_delay Unaweza kusanidi urudiaji wa utiririshaji kwa kuchelewa, lakini kuna mitego kadhaa hapa ambayo inahusiana na nafasi za urudufishaji, maoni motomoto ya kusubiri, na kadhalika. Kumbukumbu ya WAL hukuruhusu kuziepuka.

Parameter recovery_min_apply_delay ilionekana tu katika PostgreSQL 9.3. Katika matoleo ya awali, kwa urudufishaji ulioahirishwa, unahitaji kusanidi mchanganyiko kazi za usimamizi wa uokoaji (pg_xlog_replay_pause(), pg_xlog_replay_resume()) au ushikilie sehemu za WAL kwenye kumbukumbu kwa muda wa kuchelewa.

PostgreSQL hufanyaje hii?

Inafurahisha kuona jinsi PostgreSQL inavyotumia urejeshaji wa uvivu. Hebu tuangalie recoveryApplyDelay(XlogReaderState). Inaitwa kutoka kitanzi kikuu cha kurudia kwa kila ingizo kutoka kwa 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;
}

Jambo la msingi ni kwamba ucheleweshaji unatokana na muda halisi uliorekodiwa kwenye muhuri wa muda wa ahadi ya muamala (xtime) Kama unavyoona, ucheleweshaji unatumika tu kwa ahadi na hauathiri maingizo mengine - mabadiliko yote yanatumika moja kwa moja, na ahadi imecheleweshwa, kwa hivyo tutaona mabadiliko tu baada ya ucheleweshaji uliosanidiwa.

Jinsi ya kutumia nakala iliyochelewa kurejesha data

Wacha tuseme tuna mkusanyiko wa hifadhidata na nakala iliyo na ucheleweshaji wa saa nane katika uzalishaji. Hebu tuone jinsi ya kurejesha data kwa kutumia mfano kufuta njia za mkato kwa bahati mbaya.

Tulipojifunza kuhusu tatizo hilo, sisi urejeshaji wa kumbukumbu umesitishwa kwa nakala iliyoahirishwa:

SELECT pg_xlog_replay_pause();

Kwa kusitisha, hatukuwa na hatari kwamba nakala ingerudia ombi DELETE. Jambo muhimu ikiwa unahitaji wakati wa kufikiria kila kitu.

Jambo ni kwamba nakala iliyoahirishwa lazima ifikie muda kabla ya ombi DELETE. Takriban tulijua wakati halisi wa kuondolewa. Tumefuta recovery_min_apply_delay na aliongeza recovery_target_time Π² recovery.conf. Hivi ndivyo nakala hufikia wakati unaofaa bila kuchelewa:

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

Kwa mihuri ya wakati, ni bora kupunguza ziada ili usikose. Kweli, kupungua zaidi, data zaidi tunapoteza. Tena, ikiwa tutakosa ombi DELETE, kila kitu kitafutwa tena na itabidi uanze tena (au hata kuchukua nakala baridi ya PITR).

Tulianzisha tena tukio la Postgres lililoahirishwa na sehemu za WAL zilirudiwa hadi wakati uliobainishwa. Unaweza kufuatilia maendeleo katika hatua hii kwa kuuliza:

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;

Ikiwa muhuri wa muda hautabadilika tena, urejeshaji umekamilika. Kitendo kinaweza kubinafsishwa recovery_target_actionkufunga, kukuza, au kusitisha mfano baada ya kujaribu tena (imesimamishwa kwa chaguomsingi).

Hifadhidata ilirudi katika hali yake kabla ya ombi hilo la bahati mbaya. Sasa unaweza, kwa mfano, kuuza nje data. Tulihamisha data ya lebo iliyofutwa na viungo vyote vya matatizo na kuunganisha maombi na kuyahamishia kwenye hifadhidata ya uzalishaji. Ikiwa hasara ni kubwa, unaweza kukuza nakala na kuitumia kama kuu. Lakini basi mabadiliko yote baada ya hatua ambayo tumepona yatapotea.

Badala ya mihuri ya muda, ni bora kutumia vitambulisho vya muamala. Ni muhimu kurekodi vitambulisho hivi, kwa mfano, kwa taarifa za DDL (kama vile DROP TABLE), kwa kutumia log_statements = 'ddl'. Ikiwa tungekuwa na kitambulisho cha muamala, tungechukua recovery_target_xid na kuendesha kila kitu hadi kwa shughuli kabla ya ombi DELETE.

Kurudi kazini ni rahisi sana: ondoa mabadiliko yote kutoka recovery.conf na uanze upya Postgres. Replica hivi karibuni itacheleweshwa kwa saa nane tena, na tuko tayari kwa matatizo yajayo.

Faida za Urejeshaji

Na nakala iliyoahirishwa badala ya nakala rudufu, sio lazima utumie masaa mengi kurejesha picha nzima kutoka kwa kumbukumbu. Kwa mfano, hutuchukua saa tano kupata nakala ya msingi ya TB 2. Na kisha bado unapaswa kutumia WAL nzima ya kila siku ili kurejesha hali inayotakiwa (katika hali mbaya zaidi).

Nakala iliyoahirishwa ni bora kuliko nakala baridi kwa njia mbili:

  1. Hakuna haja ya kuondoa nakala zote za msingi kutoka kwa kumbukumbu.
  2. Kuna kidirisha cha saa nane kisichobadilika cha sehemu za WAL ambacho lazima kirudiwe.

Pia tunakagua kila mara ili kuona kama inawezekana kutengeneza PITR kutoka kwa WAL, na tutaona haraka upotovu au matatizo mengine na kumbukumbu ya WAL kwa kufuatilia kuchelewa kwa nakala iliyoahirishwa.

Katika mfano huu, ilituchukua dakika 50 kurejesha, ikimaanisha kwamba kasi ilikuwa GB 110 ya data ya WAL kwa saa (kumbukumbu bado ilikuwa imewashwa. AWS S3) Kwa jumla, tulitatua tatizo na kurejesha data katika saa 1,5.

Matokeo: ambapo nakala iliyoahirishwa ni muhimu (na ambapo sio)

Tumia urudufishaji uliocheleweshwa kama msaada wa kwanza ikiwa umepoteza data kimakosa na kugundua tatizo hili ndani ya ucheleweshaji uliowekwa.

Lakini kumbuka: urudufishaji sio nakala rudufu.

Kuhifadhi nakala na kurudia kuna madhumuni tofauti. Backup baridi itakuja kwa manufaa ikiwa umefanya kwa bahati mbaya DELETE au DROP TABLE. Tunafanya nakala kutoka kwa hifadhi ya baridi na kurejesha hali ya awali ya meza au hifadhidata nzima. Lakini wakati huo huo ombi DROP TABLE inatolewa tena mara moja katika nakala zote kwenye nguzo inayofanya kazi, kwa hivyo uigaji wa kawaida hautasaidia hapa. Replication yenyewe huweka hifadhidata inapatikana wakati seva za kibinafsi zinakodishwa na kusambaza mzigo.

Hata kwa nakala iliyoahirishwa, wakati mwingine tunahitaji sana hifadhi rudufu mahali salama ikiwa hitilafu ya kituo cha data, uharibifu uliofichwa, au matukio mengine ambayo hayaonekani mara moja yanatokea. Kuiga peke yake hakuna manufaa hapa.

Kumbuka. Imewashwa GitLab.com Kwa sasa tunalinda tu dhidi ya upotezaji wa data kwenye kiwango cha mfumo na haturejeshi data katika kiwango cha mtumiaji.

Chanzo: mapenzi.com

Kuongeza maoni