Біз PostgreSQL көмегімен апатты қалпына келтіру үшін жалқау репликацияны қалай пайдаландық

Біз PostgreSQL көмегімен апатты қалпына келтіру үшін жалқау репликацияны қалай пайдаландық
Репликация сақтық көшірме емес. Немесе жоқ? Төте жолдарды кездейсоқ жою арқылы қалпына келтіру үшін жалқау репликацияны қалай қолдандық.

инфрақұрылым мамандары GitLab жұмысқа жауапты GitLab.com - табиғаттағы GitLab-тың ең үлкен данасы. 3 миллион пайдаланушысы және 7 миллионға жуық жобалары бар бұл арнайы архитектурасы бар ең үлкен ашық бастапқы SaaS сайттарының бірі. PostgreSQL дерекқор жүйесі болмаса, GitLab.com инфрақұрылымы алысқа бармайды және біз деректерді жоғалтуға болатын кез келген сәтсіздіктер жағдайында ақауларға төзімділік үшін не істемейміз. Мұндай апат орын алуы екіталай, бірақ біз жақсы дайындалдық және әртүрлі резервтік көшіру және қайталау механизмдерін жинақтадық.

Репликация дерекқордың сақтық көшірмесін жасау құралы емес (төменде қараңыз). Бірақ енді біз жалқау репликацияны пайдаланып кездейсоқ жойылған деректерді қалай жылдам қалпына келтіруге болатынын көреміз: қосулы GitLab.com пайдаланушы таңбаша жойылды жоба үшін gitlab-ce және біріктіру сұраулары мен тапсырмаларымен жоғалған байланыстар.

Кешіктірілген көшірме арқылы біз деректерді небәрі 1,5 сағатта қалпына келтірдік. Қалай болғанын қараңыз.

PostgreSQL көмегімен уақытында қалпына келтіру

PostgreSQL-де дерекқордың күйін белгілі бір уақытқа қалпына келтіретін кірістірілген функция бар. деп аталады Уақытша қалпына келтіру (PITR) және репликаны жаңартып отыратын бірдей механизмдерді пайдаланады: бүкіл дерекқор кластерінің сенімді суретінен (негізгі сақтық көшірме) бастап, біз белгілі бір уақыт кезеңіне дейін күй өзгерістерінің сериясын қолданамыз.

Бұл мүмкіндікті суық сақтық көшірме жасау үшін пайдалану үшін біз жүйелі түрде базалық дерекқордың сақтық көшірмесін жасап, оны мұрағатта сақтаймыз (GitLab мұрағаттары мына жерде орналасқан). Google бұлттық қоймасы). Сондай-ақ біз алдын ала жазу журналын мұрағаттау арқылы дерекқор күйінің өзгерістерін бақылаймыз (алдын ала журналды жазыңыз, WAL). Осының барлығымен біз апатты қалпына келтіру үшін PITR жасай аламыз: біз қатенің алдында түсірілген суреттен бастаймыз және WAL мұрағатындағы өзгерістерді апатқа дейін қолданамыз.

Кешіктірілген репликация дегеніміз не?

Кешіктірілген репликация - кешігумен WAL өзгертулерін қолдану. Яғни, транзакция сағатта болды X, бірақ ол кідіріспен репликада пайда болады d сағатына X + d.

PostgreSQL жүйесінде физикалық дерекқор репликасын орнатудың 2 жолы бар: мұрағатты қалпына келтіру және ағынды репликация. Мұрағаттан қалпына келтіру, негізінен PITR сияқты жұмыс істейді, бірақ үздіксіз: біз үнемі WAL мұрағатынан өзгерістерді шығарып, оларды көшірмеге қолданамыз. А ағынды репликация WAL ағынын тікелей жоғарғы дерекқор хостынан алады. Біз мұрағаттан қалпына келтіруді қалаймыз - оны басқару оңай және өндірістік кластерден артта қалмайтын қалыпты өнімділікке ие.

Кешіктірілген сақтық көшірмені қалпына келтіруді қалай орнатуға болады

Қалпына келтіру опциялары файлда сипатталған recovery.conf. Мысал:

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'

Осы параметрлермен біз мұрағатты қалпына келтіруі бар кешіктірілген көшірмені конфигурацияладық. Мұнда қолданылған валь-е WAL сегменттерін шығару үшін (restore_command) мұрағаттан алынады және өзгертулер сегіз сағаттан кейін қолданылады (recovery_min_apply_delay). Реплика мұрағаттағы хронологиялық өзгерістерді бақылайды, мысалы, кластердің ауыстырылуына байланысты (recovery_target_timeline).

С recovery_min_apply_delay кідіріс ағынының репликациясын орнатуға болады, бірақ репликация слоттарымен, ыстық қосалқы кері байланыспен және т.б. байланысты бірнеше қателер бар. WAL мұрағаты оларды болдырмайды.

Параметр recovery_min_apply_delay тек PostgreSQL 9.3 жүйесінде пайда болды. Алдыңғы нұсқаларда кешіктірілген репликация комбинациясын қажет етеді қалпына келтіруді басқару функциялары (pg_xlog_replay_pause(), pg_xlog_replay_resume()) немесе мұрағатта WAL сегменттерін кідіріс ұзақтығына ұстаңыз.

PostgreSQL мұны қалай жасайды?

PostgreSQL жалқау қалпына келтіруді қалай жүзеге асыратынын көру қызықты. Қарап көрейік recoveryApplyDelay(XlogReaderState). -ден аталады негізгі циклды қайталау 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;
}

Қорытындысы: кідіріс транзакцияны орындау уақыт белгісінде жазылған физикалық уақытқа негізделген (xtime). Көріп отырғаныңыздай, кідіріс тек міндеттемелерге қолданылады және басқа жазбаларға әсер етпейді - барлық өзгерістер тікелей қолданылады және міндеттеме кейінге қалдырылды, сондықтан біз өзгерістерді конфигурацияланған кешігуден кейін ғана көреміз.

Деректерді қалпына келтіру үшін жалқау репликаны қалай пайдалануға болады

Өндірісте дерекқор кластері және сегіз сағаттық кешігуі бар реплика бар делік. Мысал арқылы деректерді қалай қалпына келтіруге болатынын көрейік төте жолдарды кездейсоқ жою.

Мәселе туралы білген кезде біз сақтық көшірмені қалпына келтіру кідіртілді кешіктірілген көшірме үшін:

SELECT pg_xlog_replay_pause();

Үзіліс кезінде репликаның сұрауды қайталау қаупі болмады DELETE. Сізге бәрін анықтау үшін уақыт қажет болса, пайдалы нәрсе.

Түпнұсқа: кешіктірілген көшірме сұраудан бұрынғы сәтке жетуі керек DELETE. Біз жоюдың физикалық уақытын шамамен білдік. Біз алып тастадық recovery_min_apply_delay және қосылды recovery_target_time в recovery.conf. Осылайша реплика кідіріссіз қажетті сәтке жетеді:

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

Уақыт белгілерімен жіберіп алмау үшін артық мөлшерін азайтқан дұрыс. Рас, неғұрлым азайса, соғұрлым көп деректерді жоғалтамыз. Тағы да, егер сұрауды өткізіп жіберсек DELETE, бәрі қайтадан жойылады және қайта бастауға тура келеді (немесе тіпті PITR үшін суық сақтық көшірме жасау).

Біз кешіктірілген Postgres данасын қайта бастадық және WAL сегменттері көрсетілген уақытқа дейін қайталанды. Сұрау арқылы осы кезеңде орындалу барысын бақылауға болады:

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;

Уақыт белгісі енді өзгермесе, қалпына келтіру аяқталды. Сіз әрекетті теңшей аласыз recovery_target_actionқайталаудан кейін дананы жабу, жылжыту немесе кідірту үшін (ол әдепкі бойынша кідіртеді).

Мәліметтер базасы мемлекетке сол сәтсіз өтініштен бұрын келді. Енді сіз, мысалы, деректерді экспорттай аласыз. Біз қашықтағы жапсырма деректерін және мәселелер мен біріктіру сұрауларына барлық сілтемелерді экспорттадық және оларды өндіріс дерекқорына тасымалдадық. Егер жоғалтулар үлкен болса, сіз жай ғана көшірмені алға жылжытып, оны негізгі ретінде пайдалана аласыз. Бірақ содан кейін біз қалпына келтірілген сәттен кейін барлық өзгерістер жоғалады.

Уақыт белгілерінің орнына транзакция идентификаторларын қолданған дұрыс. Бұл идентификаторларды жазу пайдалы, мысалы, DDL мәлімдемелері үшін (мысалы DROP TABLE), көмегімен log_statements = 'ddl'. Егер бізде транзакция идентификаторы болса, біз қабылдайтын едік recovery_target_xid және сұраудан бұрын транзакцияға дейін барлығын орындады DELETE.

Жұмысқа қайта оралу өте қарапайым: барлық өзгерістерді алып тастаңыз recovery.conf және postgres қайта іске қосыңыз. Жақында тағы да сегіз сағаттық кешігу болады және біз болашақ қиындықтарға дайынбыз.

Қалпына келтіру артықшылықтары

Кешіктірілген көшірмеде суық сақтық көшірменің орнына мұрағаттан бүкіл суретті қалпына келтіруге бірнеше сағат жұмсаудың қажеті жоқ. Мысалы, 2 ТБ негізгі резервтік көшірмені алу үшін бізге бес сағат қажет. Содан кейін сіз қалаған күйге (ең нашар жағдайда) қалпына келтіру үшін барлық күнделікті WAL қолдануыңыз керек.

Кешіктірілген көшірме суық сақтық көшірмеге қарағанда екі жолмен жақсырақ:

  1. Мұрағаттан негізгі сақтық көшірмені толығымен алудың қажеті жоқ.
  2. Қайталанатын WAL сегменттерінің бекітілген сегіз сағаттық терезесі бар.

Сондай-ақ, біз WAL-ды PITR-деуге болатын-болмайтынын үнемі тексеріп отырамыз және кешіктірілген көшірменің артта қалуын бақылау арқылы WAL мұрағатындағы сыбайлас жемқорлықты немесе басқа мәселелерді тез байқаймыз.

Бұл мысалда қалпына келтіру үшін бізге 50 минут қажет болды, яғни жылдамдығы сағатына 110 ГБ WAL деректерін құрады (мұрағат әлі қосулы болды) AWS S3). Барлығы 1,5 сағатта мәселені шешіп, деректерді қалпына келтірдік.

Түйіндеме: кешіктірілген көшірме қай жерде пайдалы (және қайда емес)

Деректерді кездейсоқ жоғалтып алсаңыз және конфигурацияланған кідіріс ішінде бұл апатты байқасаңыз, алғашқы көмек ретінде кешіктірілген репликацияны пайдаланыңыз.

Бірақ есте сақтаңыз: репликация сақтық көшірме емес.

Сақтық көшірме мен репликацияның мақсаттары әртүрлі. Егер сіз кездейсоқ жасаған болсаңыз, суық сақтық көшірме пайдалы болады DELETE немесе DROP TABLE. Біз суық қоймадан сақтық көшірме жасаймыз және кестенің немесе бүкіл дерекқордың алдыңғы күйін қалпына келтіреміз. Бірақ сонымен бірге сұраныс DROP TABLE жұмыс кластеріндегі барлық репликаларда бірден дерлік ойнатылады, сондықтан тұрақты репликация мұнда сақталмайды. Репликацияның өзі жеке серверлер жалға берілгенде дерекқорды қол жетімді етеді және жүктемені таратады.

Кешіктірілген көшірменің өзінде де, кенеттен деректер орталығының істен шығуы, жасырын зақымдану немесе сіз бірден байқамайтын басқа оқиғалар орын алса, бізге кейде қауіпсіз жерде сақтық көшірме қажет болады. Мұнда бір қайталаудың мағынасы жоқ.

ескерту. туралы GitLab.com біз қазір тек жүйе деңгейінде деректердің жоғалуынан қорғаймыз және пайдаланушы деңгейінде деректерді қалпына келтірмейміз.

Ақпарат көзі: www.habr.com

пікір қалдыру