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:
- Vēl nav nosūtīts: primārais serveris vai tīkls netiek līdzi.
- Nosūtīts, bet nav saglabāts: rezerves servera disks ir par lēnu, lai ierakstītu ienākošo WAL.
- Saglabāts, bet nav atjaunots: dati rezerves serverī ir drošībā, bet to piemērošana ir lēna vai apturēta. Šis ir biežākais veids un tas, ko pamana lietotāji, jo vaicājumi rezerves serverī redz tikai atjaunotos datus.
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:
- Kad rezerves serveris ir pilnībā panācis primāro, kolonnas nenokrītas līdz nullei. Tās rāda, cik ilgi aizņēma pēdējais WAL, un pēc īsa brīža neaktīvā sistēmā kļūst
NULL. Jūsu monitoringam jāizlemj, vaiNULLnozīmē "nav datu" vai "nav nobīdes". - Tās nav prognoze, cik ilgā laikā rezerves serveris panāks primāro.
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:
- 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.
- 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. - Apzināta aizkave.
recovery_min_apply_delaytīš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. - 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:
hot_standby_feedback = onpaziņo primārajam, kuras rindas vēl vajadzīgas rezerves servera vaicājumiem, un VACUUM tās patur. Atcelšanas tīrīšanas dēļ izzūd. Cena ir tāda, ka gari vaicājumi rezerves serverī tagad aizkavē tīrīšanu primārajā serverī, kas tur var radīt uzpūšanos. Kāpēc tas ir svarīgi, skaidro mūsu ceļvedis par autovacuum un uzpūšanos.- Lielāks
max_standby_streaming_delayļauj vaicājumiem rezerves serverī darboties ilgāk pirms atcelšanas, bet par lielākas nobīdes cenu. Labi atskaišu replikai, slikti rezerves serverim, uz kuru plānojat pārslēgties. - Atsevišķi rezerves serveri atsevišķiem darbiem. Viens ar atgriezenisko saiti un garām aizkavēm analītikai, otrs ar noklusējuma iestatījumiem, kas paliek tuvu primārajam, augstai pieejamībai. Bieži tas ir tīrākais risinājums.
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
- Rezerves serveris pazudis no
pg_stat_replicationprimārajā serverī. - Nobīde baitos katram solim, ar sliekšņiem, kas atbilst jūsu rakstīšanas apjomam.
- Sirdspuksta vecums katrā rezerves serverī: laika nobīde, ko nemaldina kluss primārais.
- Aizturētais WAL katram replikācijas slotam, lai miris rezerves serveris nepiepildītu disku.
pg_stat_database_conflictspieaugums lasīšanas replikās.
Galvenās atziņas
- Sadaliet nobīdi nosūtīšanā, saglabāšanā un atjaunošanā. Katrai ir citi cēloņi un risinājumi.
replay_lagnenokrītas līdz nullei, kad serveris ir panācis primāro, unnow() - pg_last_xact_replay_timestamp()aug, ja primārais ir kluss. Apvienojiet nobīdi baitos ar sirdspukstu.- Atjaunošana notiek vienā procesā, un to bieži aiztur vaicājumi rezerves serverī. Skatieties tur vispirms, ja dati pienāk, bet nav redzami.
hot_standby_feedbackapmaina atcelšanas rezerves serverī pret iespējamu uzpūšanos primārajā. Ja iespējams, izmantojiet atsevišķus rezerves serverus augstai pieejamībai un atskaitēm.- Nobīde asinhronā rezerves serverī ir potenciāls datu zudums pārslēgšanās brīdī, un atpalicis slots var piepildīt primārā servera disku.