Ինչպես մենք օգտագործեցինք հետաձգված վերարտադրությունը PostgreSQL-ով աղետի վերականգնման համար

Ինչպես մենք օգտագործեցինք հետաձգված վերարտադրությունը PostgreSQL-ով աղետի վերականգնման համար
Կրկնօրինակումը կրկնօրինակ չէ: Կամ ոչ? Ահա, թե ինչպես ենք մենք օգտագործել հետաձգված կրկնօրինակում՝ պատահաբար ջնջված դյուրանցումները վերականգնելու համար:

Ենթակառուցվածքի մասնագետներ GitLab-ը պատասխանատու է աշխատանքի համար GitLab.com - ամենամեծ GitLab օրինակը բնության մեջ: Ունենալով 3 միլիոն օգտատեր և մոտ 7 միլիոն նախագծեր, այն հանդիսանում է SaaS-ի ամենամեծ բաց կոդով կայքերից մեկը՝ նվիրված ճարտարապետությամբ: Առանց PostgreSQL տվյալների բազայի համակարգի, GitLab.com ենթակառուցվածքը հեռու չի գնա, և ինչ ենք մենք անում, որպեսզի ապահովենք անսարքությունների հանդուրժողականություն ցանկացած խափանումների դեպքում, երբ տվյալները կարող են կորցնել: Դժվար թե նման աղետ տեղի ունենա, բայց մենք լավ պատրաստված ենք և համալրված ենք պահեստային և կրկնօրինակման տարբեր մեխանիզմներով:

Կրկնօրինակումը տվյալների բազաների կրկնօրինակման միջոց չէ (տես ներքեւում) Բայց հիմա մենք կտեսնենք, թե ինչպես արագ վերականգնել պատահաբար ջնջված տվյալները՝ օգտագործելով ծույլ կրկնօրինակումը GitLab.com օգտագործողը ջնջեց դյուրանցումը նախագծի համար gitlab-ce և կորցրեց կապերը միաձուլման հարցումների և առաջադրանքների հետ:

Հետաձգված կրկնօրինակով մենք տվյալները վերականգնեցինք ընդամենը 1,5 ժամում: Տեսեք, թե ինչպես է դա եղել.

Նշեք ժամանակի վերականգնումը PostgreSQL-ով

PostgreSQL-ն ունի ներկառուցված գործառույթ, որը վերականգնում է տվյալների շտեմարանի վիճակը որոշակի ժամանակահատվածում: Այն կոչվում է Ժամանակի վերականգնում (PITR) և օգտագործում է նույն մեխանիզմները, որոնք թարմացնում են կրկնօրինակը. սկսած ամբողջ տվյալների բազայի կլաստերի հուսալի պատկերից (բազային կրկնօրինակում), մենք կիրառում ենք վիճակի մի շարք փոփոխություններ մինչև ժամանակի որոշակի կետ:

Այս հատկությունը սառը կրկնօրինակման համար օգտագործելու համար մենք պարբերաբար ստեղծում ենք տվյալների բազայի հիմնական կրկնօրինակում և պահում այն ​​արխիվում (GitLab արխիվները ապրում են Google ամպային պահեստավորում) Մենք նաև վերահսկում ենք տվյալների բազայի վիճակի փոփոխությունները՝ արխիվացնելով նախօրոք գրելու մատյանը (առաջ գրել մատյան, ՎԱԼ): Եվ այս ամենի առկայության դեպքում մենք կարող ենք 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-e WAL հատվածներ հանելու համար (restore_command) արխիվից, և փոփոխությունները կկիրառվեն ութ ժամ հետո (recovery_min_apply_delay) Կրկնօրինակը կհետևի արխիվում ժամանակացույցի փոփոխություններին, օրինակ՝ կլաստերի ձախողման պատճառով (recovery_target_timeline).

С recovery_min_apply_delay Դուք կարող եք կարգավորել հոսքային կրկնօրինակումը ուշացումով, բայց այստեղ կան մի քանի որոգայթներ, որոնք կապված են կրկնօրինակման սլոտների, տաք սպասման հետադարձ կապի և այլնի հետ: WAL արխիվը թույլ է տալիս խուսափել դրանցից:

Parameter 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կրկնելուց հետո օրինակը փակելու, խթանելու կամ դադարեցնելու համար (այն լռելյայն կասեցված է):

Տվյալների բազան վերադարձավ իր վիճակին՝ մինչ այդ անհաջող խնդրանքը։ Այժմ դուք կարող եք, օրինակ, արտահանել տվյալներ: Մենք արտահանեցինք ջնջված պիտակի տվյալները և խնդիրների և միաձուլման հարցումների բոլոր հղումները և դրանք տեղափոխեցինք արտադրության տվյալների բազա: Եթե ​​կորուստները մեծածավալ են, կարող եք պարզապես գովազդել կրկնօրինակը և օգտագործել այն որպես հիմնական։ Բայց հետո բոլոր փոփոխությունները այն կետից հետո, որին մենք վերականգնվել ենք, կկորչեն:

Ժամային դրոշմանիշների փոխարեն ավելի լավ է օգտագործել գործարքների ID-ները: Օգտակար է գրանցել այս ID-ները, օրինակ, DDL հայտարարությունների համար (օրինակ DROP TABLE), օգտագործելով log_statements = 'ddl'. Եթե ​​գործարքի ID ունենայինք, կվերցնեինք recovery_target_xid և վազեց ամեն ինչ մինչև գործարքը մինչև հարցումը DELETE.

Աշխատանքի վերադառնալը շատ պարզ է՝ հեռացնել բոլոր փոփոխությունները recovery.conf և վերագործարկեք Postgres-ը: Շուտով կրկնօրինակը կրկին կունենա ութ ժամ ուշացում, և մենք պատրաստ ենք ապագա անախորժություններին:

Վերականգնման առավելությունները

Սառը կրկնօրինակի փոխարեն հետաձգված կրկնօրինակով, դուք ստիպված չեք լինի ժամեր ծախսել արխիվից ամբողջ պատկերը վերականգնելու համար: Օրինակ, մեզանից հինգ ժամ է պահանջվում 2 ՏԲ հիմնական պահուստավորումը ստանալու համար: Եվ հետո դուք դեռ պետք է կիրառեք ամբողջ ամենօրյա WAL-ը, որպեսզի վերականգնվեք ցանկալի վիճակին (վատագույն դեպքում):

Հետաձգված կրկնօրինակն ավելի լավ է, քան սառը կրկնօրինակը երկու եղանակով.

  1. Կարիք չկա արխիվից հեռացնել ամբողջ հիմնական կրկնօրինակը:
  2. Կա WAL հատվածների ֆիքսված ութժամյա պատուհան, որը պետք է կրկնվի:

Մենք նաև անընդհատ ստուգում ենք՝ արդյոք հնարավոր է PITR պատրաստել WAL-ից, և մենք արագ կնկատենք կոռուպցիան կամ այլ խնդիրներ WAL արխիվի հետ՝ վերահսկելով հետաձգված կրկնօրինակի հետաձգումը:

Այս օրինակում մեզնից 50 րոպե պահանջվեց վերականգնելու համար, այսինքն՝ արագությունը կազմում էր ժամում 110 ԳԲ WAL տվյալներ (արխիվը դեռ միացված էր AWS S3). Ընդհանուր առմամբ, մենք լուծեցինք խնդիրը և վերականգնեցինք տվյալները 1,5 ժամում։

Արդյունքներ. որտեղ հետաձգված կրկնօրինակն օգտակար է (և որտեղ՝ ոչ)

Օգտագործեք հետաձգված կրկնօրինակումը որպես առաջին օգնություն, եթե դուք պատահաբար կորցրել եք տվյալները և նկատել եք այս խնդիրը կազմաձևված ուշացման ընթացքում:

Բայց հիշեք. կրկնօրինակումը կրկնօրինակում չէ:

Կրկնօրինակումը և կրկնօրինակումը տարբեր նպատակներ ունեն: Սառը կրկնօրինակը օգտակար կլինի, եթե պատահաբար եք ստեղծել DELETE կամ DROP TABLE. Մենք կրկնօրինակում ենք սառը պահեստից և վերականգնում աղյուսակի կամ ամբողջ տվյալների բազայի նախկին վիճակը։ Բայց միևնույն ժամանակ խնդրանքը DROP TABLE գրեթե ակնթարթորեն վերարտադրվում է աշխատանքային կլաստերի բոլոր կրկնօրինակներում, ուստի սովորական կրկնօրինակումն այստեղ չի օգնի: Replication-ը ինքնին հասանելի է պահում տվյալների բազան, երբ առանձին սերվերներ են վարձակալվում և բաշխում է բեռը:

Նույնիսկ հետաձգված կրկնօրինակի դեպքում մեզ երբեմն իսկապես անհրաժեշտ է սառը կրկնօրինակում ապահով վայրում, եթե տվյալների կենտրոնի խափանում, թաքնված վնաս կամ այլ իրադարձություններ են տեղի ունենում, որոնք անմիջապես նկատելի չեն: Միայն կրկնօրինակումը այստեղ ոչ մի օգուտ չունի:

Նշում: On GitLab.com Մենք ներկայումս պաշտպանում ենք տվյալների կորստից միայն համակարգի մակարդակով և չենք վերականգնում տվյալները օգտվողի մակարդակով:

Source: www.habr.com

Добавить комментарий