Monitorings

PostgreSQL replikācijas nobīde: kā to izmērīt, atrast cēloni un novērst

Rezerves serveris atpaliek, dati no tā ir novecojuši, un pārslēgšanās pēkšņi šķiet riskanta. Kā pareizi izmērīt PostgreSQL replikācijas nobīdi, atšķirt tīkla, diska un atjaunošanas problēmas un tikt galā ar "canceling statement due to conflict with recovery".

· 12 min lasīšanai · AG Data komanda

PostgreSQL replikācijas nobīdi ir viegli pamanīt un pārsteidzoši viegli izmērīt nepareizi. Atskaite uz rezerves servera rāda skaitļus no pirms desmit minūtēm, lietotājs kaut ko saglabā un nākamajā lapā to neredz, vai monitoringa grafiks rāda "nobīde: 0", kamēr rezerves serveris patiesībā atpaliek par stundu. Nobīde ir svarīga divu iemeslu dēļ: novecojuši dati šodien un pazaudētas transakcijas dienā, kad pārslēdzaties uz asinhronu rezerves serveri. Lūk, kā to pareizi izmērīt un noskaidrot, kura ķēdes daļa ir lēna.

Nobīde ir trīs dažādas aizkaves

Straumēšanas replikācija pārvieto WAL no primārā servera uz rezerves serveri pa soļiem. Primārais to nosūta, rezerves serveris to ieraksta, saglabā diskā (flush) un visbeidzot atjauno (replay), lai izmaiņas kļūtu redzamas vaicājumiem. Aizkave var uzkrāties jebkurā no šiem soļiem, un katram ir cits cēlonis:

Mērīšana primārajā serverī

pg_stat_replication ir viena rinda katram pieslēgtajam rezerves serverim. Salīdzinot tā LSN kolonnas ar pg_wal_lsn_diff, nobīdi var sadalīt šajās trijās daļās baitos:

SELECT application_name, client_addr, state, sync_state,
       pg_wal_lsn_diff(pg_current_wal_lsn(), sent_lsn)   AS not_sent_bytes,
       pg_wal_lsn_diff(sent_lsn, flush_lsn)              AS not_flushed_bytes,
       pg_wal_lsn_diff(flush_lsn, replay_lsn)            AS not_replayed_bytes,
       write_lag, flush_lag, replay_lag
FROM pg_stat_replication;

Kolonnas write_lag, flush_lag un replay_lag sniedz to pašu ainu laikā: cik ilgi aizņēma, līdz nesen saglabātais WAL tika ierakstīts, saglabāts un atjaunots rezerves serverī un primārais par to uzzināja. Pirms tās liekat uz paneļa, vērts zināt divas detaļas no dokumentācijas:

Ja rezerves servera pg_stat_replication vispār nav, tas neatpaliek, tas ir atvienots. Tam pienākas atsevišķs brīdinājums.

Mērīšana rezerves serverī

Rezerves serverī atjaunošanas informācijas funkcijas parāda, cik daudz WAL ir saņemts un cik piemērots:

SELECT pg_last_wal_receive_lsn() AS received,
       pg_last_wal_replay_lsn()  AS replayed,
       pg_wal_lsn_diff(pg_last_wal_receive_lsn(),
                       pg_last_wal_replay_lsn()) AS replay_backlog_bytes,
       now() - pg_last_xact_replay_timestamp()   AS since_last_replayed_commit;

Populārajai pārbaudei now() - pg_last_xact_replay_timestamp() ir slazds. Laikspiedols pieder pēdējam atjaunotajam commit, kā tas reģistrēts primārajā serverī. Ja desmit minūtes neviens neraksta primārajā serverī, šī pārbaude rāda desmit minūšu "nobīdi" rezerves serverim, kas ir pilnībā aktuāls. Tā arī paļaujas, ka abu serveru pulksteņi ir sinhronizēti. Apvienojiet to ar atlikumu baitos: liela laika vērtība ar nulli atjaunojamo baitu ir vienkārši kluss primārais serveris.

Uzticamai laika nobīdei neatkarīgi no slodzes daudzas komandas izmanto sirdspukstu: nelielu tabulu primārajā serverī, ko uzdevums ik pēc dažām sekundēm atjaunina ar pašreizējo laiku. Rezerves serverī šo vērtību salīdzina ar pulksteni. Ja sirdspuksts pārstāj kustēties, kamēr primārais darbojas, replikācija ir iestrēgusi, pat ja visi citi rādītāji izskatās labi.

Cēloņa atrašana

Kad zināt, kurš solis ir lēns, aizdomās turamo saraksti ir īsi.

Nav nosūtīts: tīkls vai primārais serveris. Lieli rakstīšanas uzplūdi, piemēram, masveida ielāde, indeksu veidošana vai liels UPDATE, var radīt WAL ātrāk, nekā savienojums ar attālu rezerves serveri spēj to pārnest. Pārbaudiet joslas platumu starp datu centriem vai pieejamības zonām un to, vai uzplūds bija vienreizējs vai nakts uzdevums, ko var izkliedēt.

Nav saglabāts: rezerves servera disks. Rezerves serverus bieži būvē uz lētākas un mazākas krātuves nekā primāro, jo tie "tikai replicē". Tie raksta tieši tikpat daudz WAL. Ja rezerves servera diskam ir mazāk IOPS vai caurlaidības, tas atpaliek katru reizi, kad primārais ir noslogots.

Nav atjaunots: piemērošanas puse. Tam ir vairāki bieži cēloņi:

  1. Atjaunošana ir viens process. Primārais WAL raksta no daudzām sesijām paralēli, bet rezerves serveris to piemēro ar vienu startēšanas procesu. Intensīvai rakstīšanas slodzei viens process var nepietikt, īpaši rezerves serverī ar lēnākiem diskiem vai CPU.
  2. Vaicājumi rezerves serverī aiztur atjaunošanu. Ja WAL atjaunošana noņemtu rindu versijas, kas joprojām vajadzīgas rezerves serverī strādājošam vaicājumam, PostgreSQL gaida šo vaicājumu līdz max_standby_streaming_delay (pēc noklusējuma 30 sekundes) un tad to atceļ. Kamēr tas gaida, atjaunošana stāv un nobīde aug.
  3. Apzināta aizkave. recovery_min_apply_delay tīši tur rezerves serveri aizmugurē, lai pasargātu no nejaušas dzēšanas. Šāds serveris nekad nedrīkst būt pārslēgšanās mērķis vai lasīšanas replika, un tas jāizslēdz no nobīdes brīdinājumiem.
  4. Atjaunošana ir apturēta. Kāds izpildīja pg_wal_replay_pause() un aizmirsa. pg_is_wal_replay_paused() to parādīs.

"canceling statement due to conflict with recovery"

Šī kļūda rezerves serverī ir 2. punkta otra puse. Dokumentācija biežāko iemeslu sauc par "agro tīrīšanu": VACUUM primārajā serverī noņem vecas rindu versijas, kas nevienai transakcijai primārajā serverī nav vajadzīgas, bet garam vaicājumam rezerves serverī vēl ir. Rezerves serveris var vai nu gaidīt un atpalikt, vai atcelt vaicājumu. Kādi konflikti rodas katrā datubāzē, var redzēt šeit:

SELECT datname, confl_snapshot, confl_lock,
       confl_bufferpin, confl_deadlock
FROM pg_stat_database_conflicts;

Iespējas ir kompromiss, un nav iestatījuma, kas uzvar visās frontēs:

Kad nobīde kļūst par dīkstāvi

Nobīde nav tikai novecojuši dati. Asinhronas replikācijas gadījumā viss, ko rezerves serveris nav saņēmis, ir zaudēts, ja primārais serveris nomirst un jūs paaugstināt rezerves serveri. Un, ja rezerves serveris izmanto replikācijas slotu, primārais patur visu WAL, ko rezerves serveris nav apstiprinājis. Tāls vai pazudis rezerves serveris var piepildīt primārā servera disku; šo gadījumu aplūkojam rakstā PostgreSQL disks pilns: kāpēc pg_wal turpina augt. Iestatījums max_slot_wal_keep_size ierobežo, cik daudz WAL slots var aizturēt.

Pārslēgšanās rīks, piemēram, Patroni, var atteikties paaugstināt rezerves serveri, kas atpaliek vairāk par konfigurēto WAL apjomu. Tas aizsargā jūsu datus, bet arī nozīmē, ka atpalikušais rezerves serveris var nebūt pieejams pārslēgšanai tieši tad, kad tas vajadzīgs.

Par ko brīdināt

  1. Rezerves serveris pazudis no pg_stat_replication primārajā serverī.
  2. Nobīde baitos katram solim, ar sliekšņiem, kas atbilst jūsu rakstīšanas apjomam.
  3. Sirdspuksta vecums katrā rezerves serverī: laika nobīde, ko nemaldina kluss primārais.
  4. Aizturētais WAL katram replikācijas slotam, lai miris rezerves serveris nepiepildītu disku.
  5. pg_stat_database_conflicts pieaugums lasīšanas replikās.

Galvenās atziņas

PostgreSQL Replikācija Replikācijas nobīde Augsta pieejamība
Sadarbība ar mums

Rezerves serveris atpaliek?

Mēs diagnosticējam PostgreSQL replikācijas nobīdi, noskaņojam rezerves serverus un ieviešam monitoringu, kas brīdina, pirms pārslēgšanās kļūst riskanta. Personīgs DBA, iknedēļas atskaites, 24/7 reakcija uz kritiskiem incidentiem.

Sazināties Vairāk no emuāra