Sut y gwnaethom ddefnyddio oedi wrth ddyblygu ar gyfer adferiad ar ôl trychineb gyda PostgreSQL

Sut y gwnaethom ddefnyddio oedi wrth ddyblygu ar gyfer adferiad ar ôl trychineb gyda PostgreSQL
Nid yw copi wrth gefn. Neu ddim? Dyma sut y gwnaethom ddefnyddio atgynhyrchu gohiriedig i adfer ar ôl dileu llwybrau byr yn ddamweiniol.

Arbenigwyr seilwaith GitLab sy'n gyfrifol am y gwaith GitLab.com - yr enghraifft GitLab fwyaf ei natur. Gyda 3 miliwn o ddefnyddwyr a bron i 7 miliwn o brosiectau, mae'n un o'r safleoedd SaaS ffynhonnell agored mwyaf gyda phensaernïaeth bwrpasol. Heb system cronfa ddata PostgreSQL, ni fydd seilwaith GitLab.com yn mynd yn bell, a beth ydym ni'n ei wneud i sicrhau goddefgarwch bai rhag ofn y bydd unrhyw fethiannau pan ellir colli data. Mae’n annhebygol y bydd trychineb o’r fath yn digwydd, ond rydym wedi paratoi’n dda ac wedi’n stocio ag amrywiol fecanweithiau wrth gefn ac atgynhyrchu.

Nid yw atgynhyrchu yn fodd o wneud copïau wrth gefn o gronfeydd data (gweler isod). Ond nawr fe welwn sut i adfer data a ddilëwyd yn ddamweiniol yn gyflym gan ddefnyddio dyblygu diog: ymlaen GitLab.com y defnyddiwr dileu'r llwybr byr ar gyfer y prosiect gitlab-ce a cholli cysylltiadau â cheisiadau a thasgau uno.

Gyda replica gohiriedig, rydym yn adennill data mewn dim ond 1,5 awr. Edrychwch sut y digwyddodd.

Adferiad pwynt mewn amser gyda PostgreSQL

Mae gan PostgreSQL swyddogaeth adeiledig sy'n adfer cyflwr cronfa ddata i bwynt penodol mewn amser. Fe'i gelwir Adfer Pwynt-mewn-Amser (PITR) ac yn defnyddio'r un mecanweithiau sy'n cadw'r replica yn gyfoes: gan ddechrau gyda chipolwg dibynadwy o'r clwstwr cronfa ddata gyfan (wrth gefn sylfaen), rydym yn cymhwyso cyfres o newidiadau cyflwr hyd at bwynt penodol mewn amser.

Er mwyn defnyddio'r nodwedd hon ar gyfer copi wrth gefn oer, rydym yn gwneud copi wrth gefn o gronfa ddata sylfaenol yn rheolaidd ac yn ei storio mewn archif (mae archifau GitLab yn byw yn Storfa cwmwl Google). Rydym hefyd yn monitro newidiadau yng nghyflwr y gronfa ddata trwy archifo'r log ysgrifennu ymlaen llaw (log ysgrifennu ymlaen llaw, WAL). A chyda hyn oll yn ei le, gallwn wneud PITR ar gyfer adferiad mewn trychineb: gan ddechrau gyda'r ciplun a gymerwyd cyn y methiant, a chymhwyso'r newidiadau o archif WAL hyd at y methiant.

Beth yw atgynhyrchu gohiriedig?

Dyblygiad diog yw cymhwyso newidiadau o CIY gydag oedi. Hynny yw, digwyddodd y trafodiad mewn awr X, ond bydd yn ymddangos yn y replica gydag oedi d mewn awr X + d.

Mae gan PostgreSQL 2 ffordd o sefydlu replica cronfa ddata ffisegol: adfer copi wrth gefn ac atgynhyrchu ffrydio. Adfer o archif, yn ei hanfod yn gweithio fel PITR, ond yn barhaus: rydym yn gyson yn adfer newidiadau o'r archif CIY a'u cymhwyso i'r replica. A dyblygiad ffrydio yn adfer y ffrwd WAL yn uniongyrchol o'r gwesteiwr cronfa ddata i fyny'r afon. Mae'n well gennym adfer archif - mae'n haws ei reoli ac mae ganddo berfformiad arferol sy'n cyd-fynd â'r clwstwr cynhyrchu.

Sut i sefydlu adferiad gohiriedig o archif

Opsiynau adfer a ddisgrifir yn y ffeil recovery.conf. Enghraifft:

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'

Gyda'r paramedrau hyn, rydym wedi ffurfweddu replica gohiriedig gydag adferiad wrth gefn. Yma mae'n cael ei ddefnyddio wal-e i echdynnu segmentau WAL (restore_command) o’r archif, a bydd newidiadau’n cael eu gweithredu ar ôl wyth awr (recovery_min_apply_delay). Bydd y replica yn gwylio am newidiadau llinell amser yn yr archif, er enghraifft oherwydd methiant clwstwr (recovery_target_timeline).

С recovery_min_apply_delay Gallwch chi sefydlu dyblygiad ffrydio gydag oedi, ond mae yna rai peryglon yma sy'n ymwneud â slotiau atgynhyrchu, adborth wrth gefn poeth, ac ati. Mae archif WAL yn caniatáu ichi eu hosgoi.

Paramedr recovery_min_apply_delay ymddangosodd yn PostgreSQL 9.3 yn unig. Mewn fersiynau blaenorol, ar gyfer dyblygu gohiriedig mae angen i chi ffurfweddu'r cyfuniad swyddogaethau rheoli adferiad (pg_xlog_replay_pause(), pg_xlog_replay_resume()) neu gadw segmentau CIY yn yr archif am gyfnod yr oedi.

Sut mae PostgreSQL yn gwneud hyn?

Mae'n ddiddorol gweld sut mae PostgreSQL yn gweithredu adferiad diog. Gadewch i ni edrych ar recoveryApplyDelay(XlogReaderState). Fe'i gelwir o prif ddolen ailadrodd am bob cofnod o 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;
}

Y gwir amdani yw bod yr oedi yn seiliedig ar yr amser ffisegol a gofnodwyd yn stamp amser ymrwymo'r trafodiad (xtime). Fel y gwelwch, mae'r oedi yn berthnasol i ymrwymiadau yn unig ac nid yw'n effeithio ar gofnodion eraill - mae pob newid yn cael ei gymhwyso'n uniongyrchol, ac mae'r ymrwymiad yn cael ei ohirio, felly dim ond ar ôl yr oedi wedi'i ffurfweddu y byddwn yn gweld y newidiadau.

Sut i ddefnyddio copi gohiriedig i adfer data

Gadewch i ni ddweud bod gennym glwstwr cronfa ddata a replica gydag oedi wyth awr yn y cynhyrchiad. Gadewch i ni weld sut i adennill data gan ddefnyddio enghraifft dileu llwybrau byr yn ddamweiniol.

Pan ddysgon ni am y broblem, fe wnaethon ni mae adfer archifau wedi'i oedi ar gyfer atgynhyrchiad gohiriedig:

SELECT pg_xlog_replay_pause();

Gydag saib, nid oedd gennym unrhyw risg y byddai'r atgynhyrchiad yn ailadrodd y cais DELETE. Peth defnyddiol os oes angen amser arnoch i ddarganfod popeth.

Y pwynt yw bod yn rhaid i'r atgynhyrchiad gohiriedig gyrraedd yr eiliad cyn y cais DELETE. Roeddem yn gwybod yn fras amser corfforol symud. Rydym wedi dileu recovery_min_apply_delay ac ychwanegodd recovery_target_time в recovery.conf. Dyma sut mae'r replica yn cyrraedd yr eiliad iawn yn ddi-oed:

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

Gyda stampiau amser, mae'n well lleihau'r gormodedd er mwyn peidio â cholli. Yn wir, po fwyaf y gostyngiad, y mwyaf o ddata y byddwn yn ei golli. Eto, os byddwn yn methu'r cais DELETE, bydd popeth yn cael ei ddileu eto a bydd yn rhaid i chi ddechrau drosodd (neu hyd yn oed gymryd copi wrth gefn oer ar gyfer PITR).

Fe wnaethom ailddechrau achos gohiriedig Postgres ac ailadroddwyd y segmentau WAL tan yr amser penodedig. Gallwch olrhain cynnydd ar y cam hwn trwy ofyn:

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;

Os na fydd y stamp amser yn newid mwyach, mae'r adferiad wedi'i gwblhau. Gellir addasu gweithredu recovery_target_actioncau, hyrwyddo, neu oedi'r enghraifft ar ôl rhoi cynnig arall arni (mae'n cael ei atal yn ddiofyn).

Dychwelodd y gronfa ddata i'w chyflwr cyn y cais anffodus hwnnw. Nawr gallwch chi, er enghraifft, allforio data. Fe wnaethom allforio'r data label wedi'i ddileu a'r holl ddolenni i faterion a cheisiadau uno a'u symud i'r gronfa ddata cynhyrchu. Os yw'r colledion ar raddfa fawr, gallwch chi hyrwyddo'r replica a'i ddefnyddio fel y prif un. Ond yna bydd pob newid ar ôl y pwynt yr ydym wedi gwella iddo yn cael ei golli.

Yn lle stampiau amser, mae'n well defnyddio IDau trafodion. Mae'n ddefnyddiol cofnodi'r IDau hyn, er enghraifft, ar gyfer datganiadau DDL (fel DROP TABLE), trwy ddefnyddio log_statements = 'ddl'. Pe bai gennym ID trafodiad, byddem yn cymryd recovery_target_xid a rhedeg popeth i lawr i'r trafodiad cyn y cais DELETE.

Mae dychwelyd i'r gwaith yn syml iawn: dileu pob newid recovery.conf ac ailgychwyn Postgres. Bydd y replica yn cael oedi o wyth awr eto, ac rydym yn barod am drafferthion yn y dyfodol.

Budd-daliadau Adfer

Gyda replica gohiriedig yn lle copi wrth gefn oer, nid oes rhaid i chi dreulio oriau yn adfer y ddelwedd gyfan o'r archif. Er enghraifft, mae'n cymryd pum awr i ni gael y copi wrth gefn 2 TB sylfaenol cyfan. Ac yna mae'n rhaid i chi gymhwyso'r CIY dyddiol cyfan o hyd i adfer i'r cyflwr dymunol (yn yr achos gwaethaf).

Mae replica gohiriedig yn well na chopi wrth gefn oer mewn dwy ffordd:

  1. Nid oes angen tynnu'r copi wrth gefn sylfaenol cyfan o'r archif.
  2. Mae yna ffenestr wyth awr sefydlog o segmentau CIY y mae'n rhaid eu hailadrodd.

Rydym hefyd yn gwirio’n gyson i weld a yw’n bosibl gwneud PITR o CIY, a byddem yn sylwi’n gyflym ar lygredd neu broblemau eraill gydag archif CIY trwy fonitro oedi’r atgynhyrchiad gohiriedig.

Yn yr enghraifft hon, cymerodd 50 munud i ni ei adfer, sy'n golygu bod y cyflymder yn 110 GB o ddata WAL yr awr (roedd yr archif yn dal i fod ymlaen Strategaeth Cymru Gyfan S3). Yn gyfan gwbl, fe wnaethom ddatrys y broblem ac adennill y data mewn 1,5 awr.

Canlyniadau: lle mae atgynhyrchiad gohiriedig yn ddefnyddiol (a lle nad yw)

Defnyddiwch oedi wrth ddyblygu fel cymorth cyntaf os colloch ddata yn ddamweiniol a sylwi ar y broblem hon o fewn yr oedi a ffurfweddu.

Ond cofiwch: nid copi wrth gefn yw atgynhyrchu.

Mae dibenion gwahanol i wneud copi wrth gefn ac atgynhyrchu. Bydd copi wrth gefn oer yn ddefnyddiol os gwnaethoch chi'n ddamweiniol DELETE neu DROP TABLE. Rydym yn gwneud copi wrth gefn o storfa oer ac yn adfer cyflwr blaenorol y tabl neu'r gronfa ddata gyfan. Ond ar yr un pryd y cais DROP TABLE yn cael ei atgynhyrchu bron ar unwaith ym mhob atgynhyrchiad ar y clwstwr gweithredol, felly ni fydd atgynhyrchu cyffredin yn helpu yma. Mae Replication ei hun yn cadw'r gronfa ddata ar gael pan fydd gweinyddwyr unigol yn cael eu rhentu ac yn dosbarthu'r llwyth.

Hyd yn oed gyda replica gohiriedig, weithiau mae gwir angen copi wrth gefn oer arnom mewn man diogel os bydd methiant canolfan ddata, difrod cudd, neu ddigwyddiadau eraill nad ydynt yn amlwg ar unwaith yn digwydd. Nid yw atgynhyrchu yn unig o unrhyw ddefnydd yma.

Nodyn. Ymlaen GitLab.com Ar hyn o bryd dim ond ar lefel y system yr ydym yn amddiffyn rhag colli data ac nid ydym yn adennill data ar lefel y defnyddiwr.

Ffynhonnell: hab.com

Ychwanegu sylw