PostgreSQL bilan ofatni tiklash uchun dangasa replikatsiyadan qanday foydalanganmiz

PostgreSQL bilan ofatni tiklash uchun dangasa replikatsiyadan qanday foydalanganmiz
Replikatsiya zaxira nusxasi emas. Yoki yo'q? Qisqa klavishlarni tasodifan o'chirib tashlash orqali tiklash uchun dangasa replikatsiyadan qanday foydalanganmiz.

infratuzilma mutaxassislari GitLab ish uchun javobgardir GitLab.com - GitLab ning tabiatdagi eng katta nusxasi. 3 million foydalanuvchi va qariyb 7 million loyihalar bilan u maxsus arxitekturaga ega bo'lgan eng yirik ochiq manba SaaS saytlaridan biridir. PostgreSQL ma'lumotlar bazasi tizimi bo'lmasa, GitLab.com infratuzilmasi uzoqqa bormaydi va biz ma'lumotlarni yo'qotishingiz mumkin bo'lgan har qanday nosozliklar uchun xatolarga chidamlilik uchun nima qilmaymiz. Bunday falokat sodir bo'lishi dargumon, lekin biz yaxshi tayyorgarlik ko'rdik va turli xil zaxira va replikatsiya mexanizmlarini to'pladik.

Replikatsiya ma'lumotlar bazasini zaxiralash vositasi emas (pastga qarang). Ammo endi biz dangasa replikatsiya yordamida tasodifan o'chirilgan ma'lumotlarni tezda qanday tiklashni ko'rib chiqamiz: yoqilgan GitLab.com foydalanuvchi yorliq olib tashlandi loyiha uchun gitlab-ce va birlashtirish so'rovlari va vazifalari bilan yo'qolgan aloqalar.

Kechiktirilgan replika bilan biz ma'lumotlarni atigi 1,5 soat ichida tikladik. Qanday bo'lganini ko'ring.

PostgreSQL yordamida bir vaqtning o'zida tiklash

PostgreSQL ma'lumotlar bazasi holatini ma'lum bir vaqtga tiklaydigan o'rnatilgan funksiyaga ega. U deyiladi Vaqtinchalik tiklash (PITR) va replikatsiyani yangilab turadigan bir xil mexanizmlardan foydalanadi: butun ma'lumotlar bazasi klasterining ishonchli suratidan (bazaviy zahira nusxasi) boshlab, biz ma'lum bir vaqtgacha bir qator holat o'zgarishlarini qo'llaymiz.

Ushbu xususiyatdan sovuq zaxiralash uchun foydalanish uchun biz muntazam ravishda bazaviy ma'lumotlar bazasining zaxira nusxasini yaratamiz va uni arxivda saqlaymiz (GitLab arxivlari mavjud Google bulutli xotirasi). Shuningdek, biz oldindan yozish jurnalini arxivlash orqali ma'lumotlar bazasi holati o'zgarishini kuzatamiz (oldinga jurnalni yozing, WAL). Va bularning barchasi bilan biz falokatni tiklash uchun PITRni amalga oshirishimiz mumkin: biz xatolikdan oldin olingan suratdan boshlaymiz va WAL arxividagi o'zgarishlarni halokatga qadar qo'llaymiz.

Kechiktirilgan replikatsiya nima?

Kechiktirilgan replikatsiya - bu WAL dan o'zgarishlarni kechiktirish bilan qo'llash. Ya'ni, tranzaktsiya bir soatda sodir bo'ldi X, lekin u replikatsiyada kechikish bilan paydo bo'ladi d bir soat ichida X + d.

PostgreSQL-da jismoniy ma'lumotlar bazasi replikasini o'rnatishning 2 yo'li mavjud: arxivni tiklash va oqimli replikatsiya. Arxivdan tiklanmoqda, mohiyatan PITR kabi ishlaydi, lekin uzluksiz: biz doimiy ravishda WAL arxividan o'zgarishlarni chiqaramiz va ularni replikaga qo'llaymiz. A oqimli replikatsiya WAL oqimini to'g'ridan-to'g'ri yuqoridagi ma'lumotlar bazasi xostidan oladi. Biz arxivdan tiklashni afzal ko'ramiz - uni boshqarish osonroq va ishlab chiqarish klasteridan orqada qolmaydigan normal ishlashga ega.

Kechiktirilgan zaxirani tiklashni qanday sozlash kerak

Qayta tiklash imkoniyatlari faylda tasvirlangan recovery.conf. Misol:

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'

Ushbu sozlamalar yordamida biz arxivni tiklash bilan kechiktirilgan nusxani sozladik. Bu yerda ishlatilgan wal-e WAL segmentlarini chiqarish uchun (restore_command) arxivdan oling va o'zgarishlar sakkiz soatdan keyin qo'llaniladi (recovery_min_apply_delay). Replika arxivdagi vaqt jadvalidagi o'zgarishlarni kuzatadi, masalan, klasterning uzilishi (recovery_target_timeline).

Π‘ recovery_min_apply_delay siz kechikish oqimini takrorlashni o'rnatishingiz mumkin, ammo replikatsiya slotlari, issiq zaxira fikr-mulohazalari va boshqalar bilan bog'liq bir nechta tuzoqlar mavjud. WAL arxivi ulardan qochadi.

Parametr recovery_min_apply_delay faqat PostgreSQL 9.3 da paydo bo'ldi. Oldingi versiyalarda kechiktirilgan replikatsiya kombinatsiyasini talab qiladi tiklashni boshqarish funktsiyalari (pg_xlog_replay_pause(), pg_xlog_replay_resume()) yoki arxivdagi WAL segmentlarini kechiktirish muddati davomida ushlab turing.

PostgreSQL buni qanday qiladi?

PostgreSQL dangasa tiklashni qanday amalga oshirishini ko'rish qiziq. Keling, ko'rib chiqaylik recoveryApplyDelay(XlogReaderState). dan chaqiriladi asosiy tsiklni takrorlash WAL dan har bir kirish uchun.

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;
}

Xulosa shuki, kechikish tranzaksiyani bajarish vaqt belgisida qayd etilgan jismoniy vaqtga asoslanadi (xtime). Ko'rib turganingizdek, kechikish faqat majburiyatlar uchun amal qiladi va boshqa yozuvlarga ta'sir qilmaydi - barcha o'zgarishlar to'g'ridan-to'g'ri qo'llaniladi va majburiyat kechiktiriladi, shuning uchun biz o'zgarishlarni faqat sozlangan kechikishdan keyin ko'ramiz.

Ma'lumotni tiklash uchun dangasa replikadan qanday foydalanish kerak

Aytaylik, bizda ishlab chiqarishda ma'lumotlar bazasi klasteri va sakkiz soatlik kechikish bilan replika mavjud. Keling, misol yordamida ma'lumotlarni qanday tiklashni ko'rib chiqaylik yorliqlarni tasodifiy o'chirish.

Muammodan xabardor bo'lganimizda, biz zahirani tiklash to'xtatildi kechiktirilgan replika uchun:

SELECT pg_xlog_replay_pause();

Pauza bilan biz replika so'rovni takrorlash xavfi yo'q edi DELETE. Agar hamma narsani tushunish uchun vaqt kerak bo'lsa, foydali narsa.

Xulosa shuki, kechiktirilgan replika so'rovdan oldin bo'lishi kerak DELETE. Biz olib tashlashning jismoniy vaqtini taxminan bilardik. Biz olib tashladik recovery_min_apply_delay va qo'shildi recovery_target_time Π² recovery.conf. Shunday qilib, replika kechiktirmasdan kerakli vaqtga etadi:

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

Vaqt belgilari bilan, o'tkazib yubormaslik uchun ortiqcha miqdorni kamaytirish yaxshiroqdir. To'g'ri, pasayish qanchalik katta bo'lsa, biz shunchalik ko'p ma'lumotlarni yo'qotamiz. Yana, agar so'rovni o'tkazib yuborsak DELETE, hamma narsa yana o'chiriladi va siz qaytadan boshlashingiz kerak bo'ladi (yoki hatto PITR uchun sovuq zaxira nusxasini olishingiz kerak).

Biz kechiktirilgan Postgres misolini qayta ishga tushirdik va WAL segmentlari belgilangan vaqtgacha takrorlandi. Ushbu bosqichda siz quyidagi so'rovlar orqali jarayonni kuzatishingiz mumkin:

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;

Vaqt tamg'asi endi o'zgarmasa, tiklash tugallangan hisoblanadi. Siz harakatni sozlashingiz mumkin recovery_target_actionQayta urinishdan keyin misolni yopish, targ'ib qilish yoki to'xtatib turish (u sukut bo'yicha pauza qiladi).

Ma'lumotlar bazasi davlatga o'sha noxush so'rovdan oldin kelgan. Endi siz, masalan, ma'lumotlarni eksport qilishingiz mumkin. Biz masofaviy yorliq ma'lumotlarini va muammolar va birlashtirish so'rovlariga barcha havolalarni eksport qildik va ularni ishlab chiqarish ma'lumotlar bazasiga o'tkazdik. Agar yo'qotishlar katta bo'lsa, siz shunchaki nusxani targ'ib qilishingiz va uni asosiysi sifatida ishlatishingiz mumkin. Ammo keyin barcha o'zgarishlar biz tiklangan paytdan keyin yo'qoladi.

Vaqt belgilari o'rniga tranzaksiya identifikatorlaridan foydalanish yaxshiroqdir. Ushbu identifikatorlarni, masalan, DDL bayonotlari uchun yozib olish foydalidir (masalan DROP TABLE), yordamida log_statements = 'ddl'. Agar bizda tranzaksiya identifikatori bo'lsa, biz qabul qilamiz recovery_target_xid va so'rovdan oldin tranzaktsiyaga qadar hamma narsani yugurdi DELETE.

Ishga qaytish juda oddiy: barcha o'zgarishlarni olib tashlang recovery.conf va postgres-ni qayta ishga tushiring. Tez orada ishora yana sakkiz soatlik kechikish bo'ladi va biz kelajakdagi muammolarga tayyormiz.

Qayta tiklash afzalliklari

Kechiktirilgan nusxa bilan, sovuq zaxira o'rniga, arxivdan butun suratni tiklash uchun soatlab vaqt sarflashingiz shart emas. Masalan, 2 TB asosiy zaxira nusxasini olish uchun bizga besh soat kerak bo'ladi. Va keyin siz hali ham kerakli holatga qaytish uchun (eng yomon holatda) butun kunlik WALni qo'llashingiz kerak.

Kechiktirilgan nusxa ikki jihatdan sovuq zaxiradan yaxshiroqdir:

  1. Arxivdan butun asosiy zaxira nusxasini olishingiz shart emas.
  2. Qayta takrorlanishi kerak bo'lgan WAL segmentlarining sakkiz soatlik qattiq oynasi mavjud.

Bundan tashqari, biz doimiy ravishda WAL-ni PITRlash mumkinmi yoki yo'qligini tekshirib turamiz va kechiktirilgan nusxaning orqada qolishini kuzatib, WAL arxividagi buzilish yoki boshqa muammolarni tezda sezamiz.

Ushbu misolda tiklash uchun 50 daqiqa vaqt ketdi, ya'ni tezligi soatiga 110 Gb WAL ma'lumotlarini tashkil etdi (arxiv hali ham yoqilgan edi. AWS S3). Umuman olganda, biz muammoni hal qildik va ma'lumotlarni 1,5 soat ichida tikladik.

Xulosa: kechiktirilgan replika qayerda foydali bo'ladi (va qaerda emas)

Agar tasodifan ma'lumotlarni yo'qotib qo'ysangiz va sozlangan kechikish ichida bu falokatni sezsangiz, birinchi yordam sifatida kechiktirilgan replikatsiyadan foydalaning.

Lekin yodda tuting: replikatsiya zaxira emas.

Zaxira va replikatsiya turli maqsadlarga ega. Agar siz tasodifan qilgan bo'lsangiz, sovuq zaxira foydali bo'ladi DELETE yoki DROP TABLE. Biz sovuq ombordan zaxira nusxasini yaratamiz va jadval yoki butun ma'lumotlar bazasining oldingi holatini tiklaymiz. Lekin ayni paytda so'rov DROP TABLE deyarli bir zumda ishlaydigan klasterdagi barcha replikalarda takrorlanadi, shuning uchun muntazam replikatsiya bu erda saqlanmaydi. Replikatsiyaning o'zi alohida serverlar ijaraga olinganda ma'lumotlar bazasini mavjud bo'lib qoldiradi va yukni taqsimlaydi.

Kechiktirilgan nusxada ham, ba'zida ma'lumotlar markazining ishlamay qolishi, yashirin shikastlanish yoki siz darhol sezmaydigan boshqa hodisalar bo'lsa, biz ba'zan xavfsiz joyda sovuq zaxiraga muhtojmiz. Bu erda bitta replikatsiyadan hech qanday ma'no yo'q.

nota. O'sha GitLab.com biz hozirda faqat tizim darajasida ma'lumotlarni yo'qotishdan himoya qilamiz va foydalanuvchi darajasida ma'lumotlarni tiklamaymiz.

Manba: www.habr.com

a Izoh qo'shish