Pehea mākou i hoʻohana ai i ka replication lohi no ka hoʻihoʻi ʻana i ka pōʻino me PostgreSQL

Pehea mākou i hoʻohana ai i ka replication lohi no ka hoʻihoʻi ʻana i ka pōʻino me PostgreSQL
ʻAʻole kākoʻo ka hoʻopiʻi. ʻAʻole paha? Eia ke ʻano o kā mākou hoʻohana ʻana i ka hoʻopiʻi hoʻopanee e hoʻihoʻi mai ka holoi ʻana i nā ʻaoʻao pōkole.

Nā loea hoʻolālā Na GitLab ke kuleana no ka hana GitLab.com - ka mea nui loa ʻo GitLab ma ke ʻano. Me 3 miliona mau mea hoʻohana a kokoke i 7 miliona mau papahana, ʻo ia kekahi o nā punaewele punahele nui loa o SaaS me kahi hoʻolālā hoʻolaʻa. Me ka ʻole o ka ʻōnaehana waihona PostgreSQL, ʻaʻole e hele lōʻihi ka ʻōnaehana GitLab.com, a he aha kā mākou e hana ai e hōʻoia i ka hoʻomanawanui hewa ʻana i ka wā e nalowale ai ka ʻikepili. ʻAʻole paha e hiki mai kēlā pōʻino, akā mākaukau maikaʻi mākou a hoʻopaʻa ʻia me nā ʻano hana hoʻihoʻi like ʻole.

ʻAʻole ʻo ka hoʻopili hou ʻana i mea e kākoʻo ai i nā ʻikepili (e nānā ma lalo). Akā i kēia manawa e ʻike mākou pehea e hoʻihoʻi koke ai i ka ʻikepili i hoʻopau ʻia me ka hoʻohana ʻana i ka lazy replication: on GitLab.com mea hoʻohana holoi ʻia ka pōkole no ka papahana gitlab-ce a nalowale nā ​​pilina me nā noi hoʻohui a me nā hana.

Me kahi kope hoʻopanee ʻia, ua hoʻihoʻi mākou i ka ʻikepili i nā hola 1,5 wale nō. E nana i ka hana ana.

Kuhi i ka manawa hoʻihoʻi me PostgreSQL

Loaʻa i ka PostgreSQL kahi hana i kūkulu ʻia e hoʻihoʻi i ke kūlana o kahi waihona i kahi kikoʻī i ka manawa. Ua kapa ʻia Hoʻihoʻi kiko-i-manawa (PITR) a hoʻohana i nā ʻano hana like e mālama ai i ka replica i kēia lā: e hoʻomaka me kahi kiʻi paʻi hilinaʻi o ka pūʻulu waihona waihona holoʻokoʻa (base backup), hoʻohana mākou i kahi ʻano o nā hoʻololi mokuʻāina a hiki i kahi manawa.

No ka hoʻohana ʻana i kēia hiʻohiʻona no ka hoʻihoʻi anu, hana mau mākou i kahi waihona waihona waihona kumu a mālama iā ia i loko o kahi waihona (nā waihona ʻo GitLab e noho ana ma Waihona ao Google). Nānā pū mākou i nā loli i ka mokuʻāina o ka waihona ma ka hoʻopaʻa ʻana i ka log kākau mua (kākau-mua log, WAL). A me kēia mau mea a pau, hiki iā mākou ke hana i kahi PITR no ka hoʻihoʻi ʻana i ka pōʻino: e hoʻomaka me ke kiʻi paʻi i lawe ʻia ma mua o ka hāʻule ʻana, a me ka hoʻohana ʻana i nā hoʻololi mai ka waihona WAL a hiki i ka hemahema.

He aha ka hana hoʻopanee ʻia?

ʻO ka hoʻopiʻi palaualelo ka hoʻohana ʻana i nā loli mai WAL me ka lohi. ʻO ia hoʻi, ua hana ʻia ke kālepa i loko o hoʻokahi hola X, akā e hōʻike ʻia ma ke kope me ka lohi d i ka hora X + d.

Loaʻa iā PostgreSQL 2 mau ala e hoʻonohonoho ai i kahi kope ʻikepili kino: hoʻihoʻi hoʻihoʻi a hoʻihoʻi hou. Hoʻihoʻi ʻia mai kahi waihona, hana maoli e like me PITR, akā hoʻomau: lawe mau mākou i nā loli mai ka waihona WAL a hoʻopili iā lākou i ke kope. A hoʻopio kahe ana kiʻi pololei i ke kahawai WAL mai ka pūʻali waihona waihona ma luna. Makemake mākou i ka hoʻihoʻi ʻana i ka waihona - ʻoi aku ka maʻalahi o ka hoʻokele ʻana a loaʻa ka hana maʻamau e hoʻomau i ka pūʻulu hana.

Pehea e hoʻonohonoho ai i ka hoʻihoʻi lohi ʻana mai kahi waihona

Koho Hoola i wehewehe ʻia ma ka faila recovery.conf... Laʻana:

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'

Me kēia mau ʻāpana, ua hoʻonohonoho mākou i kahi kope i hoʻopaneʻe ʻia me ka hoʻihoʻi hoʻihoʻi. Maanei ua hoʻohana ʻia wal-e e unuhi i nā ʻāpana WAL (restore_command) mai ka waihona, a e hoʻohana ʻia nā loli ma hope o ʻewalu hola (recovery_min_apply_delay). E nānā ka replica no nā hoʻololi ʻana o ka manawa i loko o ka waihona, no ka laʻana ma muli o kahi hāʻule puʻupuʻu (recovery_target_timeline).

С recovery_min_apply_delay Hiki iā ʻoe ke hoʻonohonoho i ka hoʻopiʻi kahe ʻana me ka lohi, akā aia kekahi mau pitfalls ma aneʻi e pili ana i nā slot replication, manaʻo hoʻokipa wela, a pēlā aku. Hiki i ka waihona WAL ke pale aku iā lākou.

ʻO ka pākuhi recovery_min_apply_delay ʻike wale ʻia ma PostgreSQL 9.3. I nā mana o mua, no ka hoʻopiʻi hoʻopanee ʻana pono ʻoe e hoʻonohonoho i ka hui nā hana hoʻoponopono hoʻihoʻi (pg_xlog_replay_pause(), pg_xlog_replay_resume()) a i ʻole e paʻa i nā ʻāpana WAL ma ka waihona no ka lōʻihi o ka lohi.

Pehea e hana ai ʻo PostgreSQL i kēia?

He mea hoihoi ia ke ʻike pehea e hoʻokō ai ʻo PostgreSQL i ka hoʻōla palaualelo. E nana kakou recoveryApplyDelay(XlogReaderState). Kāhea ʻia mai ka puka hana hou nui no kēlā me kēia komo ʻana mai 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;
}

ʻO ka laina lalo, ʻo ka lohi ʻana e pili ana i ka manawa kino i hoʻopaʻa ʻia i ka timestamp commit transaction (xtime). E like me kāu e ʻike ai, pili wale ka lohi i nā commits a ʻaʻole pili i nā komo ʻē aʻe - ua hoʻopili pololei ʻia nā hoʻololi a pau, a ua lohi ka commit, no laila e ʻike wale mākou i nā loli ma hope o ka lohi i hoʻonohonoho ʻia.

Pehea e hoʻohana ai i kahi kope lohi e hoʻihoʻi i ka ʻikepili

E ʻōlelo kākou he pūʻulu waihona waihona a me kahi kope me ka lohi ʻewalu hola i ka hana ʻana. E ʻike kākou pehea e hoʻihoʻi ai i ka ʻikepili me ka hoʻohana ʻana i kahi laʻana ka holoi wale ʻana i nā ʻaoʻao pōkole.

Ke aʻo mākou e pili ana i ka pilikia, mākou Ua hoʻomaha ʻia ka hoʻihoʻi ʻana o ka waihona no ke kope hoʻopanee ʻia:

SELECT pg_xlog_replay_pause();

Me ka hoʻomaha, ʻaʻohe o mākou pilikia e hana hou ke kope i ka noi DELETE. He mea pono inā makemake ʻoe i ka manawa e noʻonoʻo ai i nā mea āpau.

ʻO ka manaʻo, ʻo ka replica i hoʻopanee ʻia e hiki i ka manawa ma mua o ke noi DELETE. Ua ʻike mākou i ka manawa kino o ka wehe ʻana. Ua holoi mākou recovery_min_apply_delay a hoʻohui ʻia recovery_target_time в recovery.conf. ʻO kēia ke ala e hiki ai ke kope i ka manawa kūpono me ka kali ʻole:

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

Me nā hōʻailona manawa, ʻoi aku ka maikaʻi o ka hoʻohaʻahaʻa ʻana i ka nui i ʻole e nalo. ʻOiaʻiʻo, ʻoi aku ka nui o ka emi ʻana, ʻoi aku ka nui o ka ʻikepili i nalowale. Eia hou, inā haʻalele mākou i ka noi DELETE, e holoi hou ʻia nā mea a pau a pono ʻoe e hoʻomaka hou (a i ʻole e lawe i kahi kope anu no PITR).

Hoʻomaka hou mākou i ka manawa Postgres i hoʻopaneʻe ʻia a ua hana hou ʻia nā ʻāpana WAL a hiki i ka manawa i ʻōlelo ʻia. Hiki iā ʻoe ke hahai i ka holomua ma kēia pae ma ka nīnau ʻana:

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;

Inā ʻaʻole e loli hou ke kaha manawa, ua pau ka hoʻihoʻi ʻana. Hiki ke hoʻololi i ka hana recovery_target_actione pani, hoʻolaha, a hoʻomaha paha i ka laʻana ma hope o ka hoʻāʻo hou ʻana (ua hoʻokuʻu ʻia ma ka paʻamau).

Ua hoʻi ka waihona i kona mokuʻāina ma mua o kēlā noi pōʻino. I kēia manawa hiki iā ʻoe, no ka laʻana, hoʻoiho i ka ʻikepili. Hoʻokuʻu aku mākou i ka ʻikepili lepili i holoi ʻia a me nā loulou āpau i nā pilikia a hoʻohui i nā noi a hoʻoneʻe iā lākou i loko o ka waihona hana. Inā nui nā poho, hiki iā ʻoe ke hoʻolaha wale i ka replica a hoʻohana iā ia ma ke ʻano nui. Akā, e nalowale nā ​​hoʻololi a pau ma hope o ka helu i loaʻa iā mākou.

Ma kahi o nā timestamp, ʻoi aku ka maikaʻi o ka hoʻohana ʻana i nā ID kālepa. Pono e hoʻopaʻa i kēia mau ID, no ka laʻana, no nā ʻōlelo DDL (e like me DROP TABLE), ma ka hoʻohana ʻana log_statements = 'ddl'. Inā loaʻa iā mākou kahi ID kālepa, lawe mākou recovery_target_xid a holo i nā mea a pau i lalo i ke kālepa ma mua o ka noi DELETE.

He mea maʻalahi loa ka hoʻi ʻana i ka hana: wehe i nā hoʻololi a pau mai recovery.conf a hoʻomaka hou i ka Postgres. E hiki koke mai ana ka lohi hou ana o ka kope, a ua makaukau makou no na pilikia e hiki mai ana.

Nā Pōmaikaʻi Hoʻihoʻi

Me kahi kope i hoʻopaneʻe ʻia ma kahi o kahi waihona anu, ʻaʻole pono ʻoe e hoʻolimalima i nā hola e hoʻihoʻi i ke kiʻi holoʻokoʻa mai ka waihona. No ka laʻana, lawe mākou i ʻelima mau hola e kiʻi i ka waihona kumu 2 TB āpau. A laila pono ʻoe e hoʻopili i ka WAL āpau i kēlā me kēia lā e hoʻihoʻi i ke kūlana i makemake ʻia (i ka hihia ʻino loa).

ʻOi aku ka maikaʻi o kahi kope i hoʻopaneʻe ʻia ma mua o kahi waihona anu ma nā ala ʻelua:

  1. ʻAʻole pono e wehe i ka waihona kumu a pau mai ka waihona.
  2. Aia kekahi puka makani ʻewalu hola o nā ʻāpana WAL pono e hana hou ʻia.

Ke nānā mau nei mākou e ʻike inā hiki ke hana i kahi PITR mai WAL, a e ʻike koke mākou i ka palaho a i ʻole nā ​​pilikia ʻē aʻe me ka waihona WAL ma ka nānā ʻana i ka lag o ka replica i hoʻopaneʻe ʻia.

Ma kēia hiʻohiʻona, lawe mākou i 50 mau minuke e hoʻihoʻi, ʻo ia hoʻi, ʻo ka wikiwiki ka 110 GB o ka ʻikepili WAL i kēlā me kēia hola (ua paʻa ka waihona. AWS S3). I ka huina, ua hoʻoponopono mākou i ka pilikia a hoʻihoʻi i ka ʻikepili i nā hola 1,5.

Nā hualoaʻa: kahi e pono ai ke kope i hoʻopaneʻe ʻia (a inā ʻaʻole ia)

E hoʻohana i ka hoʻopiʻi lohi ma ke ʻano he kōkua mua inā nalowale ʻoe i ka ʻikepili a ʻike i kēia pilikia i loko o ka lohi i hoʻonohonoho ʻia.

Akā, e hoʻomanaʻo: ʻaʻole hoʻihoʻi ka hoʻihoʻi.

He mau kumu like ʻole ka hoʻihoʻi ʻana a me ka hana hou ʻana. Hiki ke mālama ʻia kahi hoʻihoʻi anuanu inā hana ʻole ʻoe DELETE ai ole ia, DROP TABLE. Hana mākou i kahi waihona mai kahi mālama anu a hoʻihoʻi i ke kūlana mua o ka papaʻaina a i ʻole ka ʻikepili holoʻokoʻa. Akā i ka manawa like ke noi DROP TABLE ʻaneʻane e hana hou ʻia i loko o nā kope a pau ma ka pūʻulu hana, no laila ʻaʻole kōkua ka hoʻopili maʻamau ma aneʻi. Mālama ʻo Replication iā ia iho i ka waihona i loaʻa i ka wā e hoʻolimalima ʻia ai nā kikowaena hoʻokahi a puʻunaue i ka ukana.

ʻOiai me kahi kope i hoʻopaneʻe ʻia, pono mākou i kekahi manawa i kahi hoʻihoʻi anu ma kahi palekana inā hiki ʻole kahi kikowaena data, poino huna, a i ʻole nā ​​​​hanana ʻē aʻe i ʻike ʻole ʻia. ʻAʻole pono ka hoʻopili wale ʻana ma ʻaneʻi.

i hoʻopuka. Ma ka GitLab.com I kēia manawa, pale wale mākou i ka nalowale o ka ʻikepili ma ka pae ʻōnaehana a ʻaʻole e hoʻihoʻi i ka ʻikepili ma ka pae mea hoʻohana.

Source: www.habr.com

Pākuʻi i ka manaʻo hoʻopuka