PostgreSQL менен кырсыкты калыбына келтирүү үчүн жалкоо репликацияны кантип колдондук

PostgreSQL менен кырсыкты калыбына келтирүү үчүн жалкоо репликацияны кантип колдондук
Репликация камдык эмес. Же жок? Жарлыктарды кокустан жок кылып, калыбына келтирүү үчүн жалкоо репликацияны кантип колдондук.

инфраструктура боюнча адистер GitLab иш үчүн жооптуу GitLab.com - жаратылыштагы GitLab эң чоң инстанциясы. 3 миллион колдонуучу жана дээрлик 7 миллион долбоорлор менен, ал атайын архитектурасы менен эң чоң ачык булактуу SaaS сайттарынын бири. PostgreSQL маалымат базасы тутуму болбосо, GitLab.com инфраструктурасы алыска барбайт жана биз кандайдыр бир катачылыктарга чыдамкайлык үчүн эмне кылбайсыз, сиз маалыматтарды жоготуп аласыз. Мындай катастрофанын болушу күмөн, бирок биз жакшы даярдандык жана ар кандай резервдик жана репликация механизмдерин камдап алдык.

Репликация сиздин базанын камдык көчүрмөсү эмес (төмөндө карагыла). Бирок азыр биз жалкоо репликацияны колдонуп кокустан жок кылынган маалыматтарды кантип тез калыбына келтирүүнү көрөбүз: on 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ды PITRedге болорун текшерип турабыз жана кечиктирилген репликанын артта калгандыгын көзөмөлдөө менен WAL архивиндеги коррупцияны же башка көйгөйлөрдү тез байкайбыз.

Бул мисалда, калыбына келтирүү үчүн бизге 50 мүнөт кетти, башкача айтканда, ылдамдыгы саатына 110 ГБ WAL маалыматын түздү (архив дагы эле күйүк болчу. AWS S3). Жалпысынан 1,5 саатта маселени чечип, маалыматтарды калыбына келтирдик.

Кыскача маалымат: кечиктирилген реплика кайсы жерде пайдалуу (жана кайда эмес)

Кокус маалыматтарды жоготуп, конфигурацияланган кечиктирүүдө бул кырсыкты байкасаңыз, биринчи жардам катары кечиктирилген репликацияны колдонуңуз.

Бирок эсиңизде болсун: репликация резервдик эмес.

Камдык көчүрмө жана репликация ар кандай максаттарга ээ. Эгер кокусунан жасалган болсоңуз, муздак резервдик көчүрмө пайдалуу болот DELETE же DROP TABLE. Биз муздак сактагычтан резервдик көчүрмөнү жасайбыз жана үстөлдүн же бүтүндөй маалымат базасынын мурунку абалын калыбына келтиребиз. Бирок ошол эле учурда өтүнүч DROP TABLE жумушчу кластердеги бардык репликаларда дээрлик заматта кайра чыгарылат, андыктан үзгүлтүксүз репликация бул жерде сакталбайт. Репликациянын өзү жеке серверлер ижарага берилгенде маалымат базасын жеткиликтүү кармап, жүктү бөлүштүрөт.

Кечиккен реплика менен да, биз кээде чындап эле коопсуз жерде муздак резервдик көчүрмөнү талап кылабыз, эгер күтүлбөгөн жерден маалымат борбору иштебей калса, жашыруун бузулуулар же сиз дароо байкабай турган башка окуялар. Бул жерде бир кайталоонун мааниси жок.

пикир. боюнча GitLab.com биз учурда система деңгээлинде маалыматтарды жоготуудан гана коргойбуз жана колдонуучу деңгээлинде маалыматтарды калыбына келтирбейбиз.

Source: www.habr.com

Комментарий кошуу