db.dobo.sk

Postgres – vsetko, co si chtel vediet, ale bal sa spytat svojho seniora, aby si nevypadal ako jelito 06. Replikacie.

7 komentárov

Replikacie zabezpecuju:

  1. HA (high availability; vypadok jedneho serveru), alebo
  2. LB (load balancing; rozlozenie zataze)

Je mozne to implementovat roznymi sposobmi (tu je kompletny prehlad, ja sa zaoberam len 2 najcastejsimi sposobmi), vynikajuci prehlad moznych replikacnych topologii je uvedeny tu. Replikovat je mozne synchronne a asynchronne – je to vzdycky deal medzi konzistenciou dat a vykonom. Co znamena synchronny? Znamena konzistenciu dat medzi replikovanymi nodmi – v pripade synchronneho zapisu master vzdy caka na potvrdenie, ze slave data tiez zapisal a len potom ich zapise aj on sam na sebe. Vykonnostne sa samozrejme spotrebuva strojovy cas na “cakanie”.

                    +---------------------------------------------------+
                    |                                                   |
                    |             Replication in PostgreSQL             |
                    |                                                   |
                    +-+-----------------------------------------------+-+
                      |                                               |
                      |                                               |
              +-------v----+                                      +---v-------+
              |  Physical  |                                      |  Logical  |
              +-+---------++                                      +-----+-----+
                |         |                                             |
                |         |                                             |
+---------------v+       +v------------+                       +--------v--------+
|  Log Shipping  |       |  Streaming  |                       |     Logical     |
+----------------+       ++----------+-+                       |   Replication   |
                          |          |                         |      Slots      |
                          |          |                         +--------+--------+
                          |          |                                  |
                          |          |                                  |
              +-----------v---+   +--v--------------+          +--------v--------+
              |    Without    |   |  With Physical  |          |  Subscriptions  |
              |  Replication  |   |   Replication   |          +-----------------+
              |     Slots     |   |      Slots      |
              +---------------+   +-----------------+

 

U postgresu su dva zakladne typy replikacii: physical replication a logical replication (via replication slots). Fyzicka – replikuju sa fyzicky vsetky WAL logy a hlavnou nevyhodou je, ze sa musi replikovat uplne vsetko v ramci clusteru (neda sa ani samostatna databaza). Logical (pritomna od verzie 10) je trochu ina salka kavy – je vlatne rozparsovanie údajov vo wal logoch spat do SQL a to sa vyberovo posle na repliku (t.j. da sa to granulovat len na niektore objekty a zaznamy).

Existuje este oldschool replikacia archivovanim logov na repliku (Log shipping). Proste je v archive commandu primaru nadefinovany typicky rsync, ktory cele subory wal logov archivuje na repliku, ktora si ich prehraje. Nazyva sa to aj PITR (point-in-time-recovery). Vid komentare k prikladu validneho pouzitia.

Streaming replication

Je v principe posielanie zaznamov z WAL logov medzi primarom a standby serverom. Standby server (alebo viacej serverov) dohrava logy a udrzuje sa up to date s primarom po TCP koneksne. Na rozdiel od “log shippinu (PITR)” sa teda necaka na cely log, ale kazdy novy zaznam vo wal logu na primarnom clusteri sa posiela na standby. Standardne je to synchronna replikacia. Jak to funguje:

Na primare je spusteny proces walsender

Na standby su procesy dva – startup a walreceiver

Faza startup – startup nastartuje walreceiver, ktory sa snazi dosiahnut na primar. Pokial dosiahne a dostane odpoved, naviaze sa spojenie a walreceiver posle posledne LSN, ktore ma. Faza catch-up – Walsender si ho porovna so svojim LSN a pokial sa lisia, zacne dohravanie WAL logov tak, aby sa vyrovnali. Faza streaming –  ked sa LSN vyrovnaju a stanby “dobehol” primar, tak uz sa synchronne streamuju data, coz je rovnovazny a zelany stav. Specialna faza je faza backup, kde sa streamovanie pouziva pre ucely pg_basebackup. Tieto fazy sa daju zistit dotazom, ktory vylistuje databazy, v akom su stave:

SELECT * FROM pg_stat_replication;

Otazka: co sa stane, ak standby napriklad zbuchol, nejaku dobu nebezal a medzitym na primare vyexpirovali (odrotovali) nejake WAL logy? Odpoved: ste v pycy, toto je nevyhoda streaming replication, neda sa to dohrat do zelaneho stavu. Prave tento problem riesi stremaing replication cez sloty – slot si udrzuje prehlad o replikacii a pokial nedoslo k prehraniu zazanamov na replike, tak nepovoli odrotovanie logu na primare (tym ovsem moze nastat to, ze sa zaplni wal_log voluma). Ale tento problem vas hned palit nebude, pretoze, ked padne standby a replikacia je nastavena synchronne, tak primar ma tu blbu vlastnost, ze nedokonci transakcie a nepovoli nove (stale sa snazi dostat potvrdenie od standby serveru, pretoze synchronne), coz je krajne neprijemne. Jedina ochrana proti tomu je v konfe vyprazdnit, alebo zakomentovat synchronous_standby_names = ” a znova nacitat konfiguraciu db servra.

Primar ma info o aktualnom diani na stanby serveroch, vie, v akom stave sa nachadzaju na nich WAL logy (su zapisane? flushnute? prehrate?) a to nasledovnym dotazom:

SELECT
application_name AS host,
write_location AS write_LSN,
flush_location AS flush_LSN,
replay_location AS replay_LSN
FROM pg_stat_replication;

Dobry clanok o streaming replication na SeveralNines je tu.

Zatialco systemovy view pg_stat_replication je zistovany na primare, na replike tuto ulohu plni pg_stat_wal_receiver. Nie su identicke, receiver pochopitelne nema tolko informacii, ako primar (nevie napr. nic o laggovani…).

Logical replication

Logicka replikacia, ako som spomenul, umoznuje replikovat medzi rozdielnymi verziami PG a hlavne umoznuje replikovat len casti clusteru (od DB az po jedinu tabulku). Ma rozne implementacie, najznamejsie 2 – “in-core logical replication“, coz je vbuildena vlastnost v Postgrese;  a pomocou externeho modulu pglogical od 3. strany (2nd quadrant).

Vlastnosti logickej replikacie:

  • LR je zalozene na modeli publication – subscriber. Master Postgres (publisher; CREATE PUBLICATION) publikuje vybrane data a Stanby node (subscriber; CREATE SUBSCRIPTION) ich konzumuje.
  • Publisher moze mat viac subscriberov a subscriber moze byt zaroven publisherom
  • Technicky to nie je az tak odlisne od streaming replikation – pracuje sa s WAL logmi, ktore su na strane publishera rozparsovane a je z nich posielana len ta informacia, ktora je nastavena vo filtroch pre publishing. V zasade parser rozparsuje informaciu vo WAL logoch na nejake pseudo SQL. Az toto je walsendrom posielane na target.
  • Technicky sa to deje cez replikacne sloty – Db objekty, ktore citaji WAL logy a posielaju informacie dalej. Az je informacia zkonzumovana subscriberom, WAL log je oznaceny ako zrely na rotovanie.
  • Pozor. LR nereplikuje DDL! T.j. schemy sa musia urobit rucne dopredu na subscriber DB. Taktiez je tam spusta obmedzeni, co sa tyka struktury DB objektov (napr. nazvy a typy columnov musia byt rovnake a pod.)…
  • Je zasadny rozdiel v praci medzi in-core replikaciou a pglogical. In-core sa ovlada vyhradne SQL syntaxou, pglogical volanim funkcii.

nativna logicka replikacia

Publisher sa vytvara  CREATE PUBLICATION a meni sa ALTER PUBLICATION, vsetky vytvorene publikacie su v pg_publication

Subscriber sa vytvara CREATE SUBSCRIPTION a meni sa ALTER SUBSCRIPTION, vytvorene subskripcie su v katalogu pg_subscription. Akonahle sa vytvori subsckripcia, ta sa “prisaje” na replikacny slot, ktory sa automaticky vytvori na publisherovi.

CREATE PUBLICATION pub01 FOR TABLE nazov_tabulky;
CREATE SUBSCRIPTION sub01 CONNECTION 'host=hostname_publisher port=5432 user=postgres password=postgres dbname=postgres' PUBLICATION pub01;

Natívna logická replikácia má niekoľko hookov, viď vyššie – ako sa s nimi popasovať:

DDL

Keďže DDL sa logickou replikáciou nekopíruje, je nutné pred tým, ako sa začne replikovať, urobiť na slaveu štruktúru objektov, ktorá zodpovedá štruktúre replikovaných objektov na masterovi:

pg_dump -U REPLIKACNY_USER -h MASTER_HOSTNAME -s -t MASTER_DB | psql -U postgres SLAVE_DB

PKs

Pokial su na masterovej databázi tabuľky bez PK, tak sa replikácia spustí a všetko sa bude tváriť OK. Ale ak apka urobí UPDATE na primárnej databázi, tak sa položí (UPDATE neprebehne), pretože chýva PK a nie je možné z hľadiska replikácie identifiokvať, kde update prebehol. Ideálny sposob, ako zabiť infraštruktúru…

Sekvencie

DDL sekvencií je možné prekopírovať na slave, ale samotná inkrementálna rada sekvencie sa nebude replikovať. To je mrzuté, pretože pri prípadnom INSERTE na slaveu to pravdepodobne vyhodí chybu – sekvencia má totižto vlastnú radu, ktorá može kolidovať s už prereplikovanými datami (PK violence). Sekvencie na slaveu je nutno “resetovať” tak, aby NEXTVAL začínal vyššie, než zreplikovaný LASTVAL. Buď ručne, alebo pomocou tejto rutiny automaticky, pokiaľ je sekvencií viac….

 

pglogical

1. Pglogical je extension do postgresu, primarne na replikacie. Dokaze ale viac – aj tahat data z frontovych/message systemov typu RabbitMQ, Kafka a tak.

2. Vraj to na rozdiel od klasickej LR zvlada aj DDL.

3. Pozor, nezvlada to replikaciu medzi DBs s rozdielnym kodovanim. Ergo drz sa osvedceneho a vzdy pouzival UTF-8.

3. Vzhladom k tomu, ze to umoznuje replikovat medzi verziami 9-11, da sa to pouzit na upgrade (data sa odreplikuju na novsiu verziu)

4. V konfigu postgresu musi byt nastavene: wal_level = logical a max_replication_slots = ‘cislo’ (na publisheru i subscriberu) a je nutne nastavit aj workery.

5. Základny systemovy view pre prehlad logickej replikacie je na subscriberovi pg_stat_subscription.

6. Dotaz na nastavenie pglogicalu na bežiacom stroji: select * from pg_settings where name~’pglogical\.’;

Kompletne o pglogical na webe autorov tu.

pglogical – streamovací failover a logické repliky pod ním

Máme následnú infraštruktúru: master, slave (replikovaná fyzickou stream replikou) a pod mastrom sú ďalšie Postgresql subscribery, ktoré logicky replikujú z neho za pomocí pglogical. Jak to celé nakonfignúť na plnohodnotný failover = keď sa položí master, tak jeho úlohu prevezme slave a logická replikácia sa tiež “prenesie” tak, aby subscribery plynule pokračovali ďalej…

  1. Najprv sa musia zreplikovať z mastra na slave i logické replikačné sloty. To sa udeje default, pokiaľ sa pri fyzickej replikácii použije pg_basebackup, ale je možné to explicitne uviesť (a tým niektoré sloty vynechať) parametrom pglogical.synchronize_failover_slot_names
  2. Pri súbežnej fyzickej a logickej replikácii sú kľúčové pozície replikačných slotov. Je nutné, aby stream slot medzi mastrom a slaveom bol “LSN napred” pred LSN logickými replikami. Ak totižto dojde k tomu, že master odreplikuje skor na subscribery a vzápatí padne, tak slave nemá LSN, na ktoré by mohli subscribery naviazať…. To, že sa najprv fyzicky odreplikuje na slave a až potom na subscribery, zabezpečuje alter system set pglogical.standby_slot_names = ‘nazov_fyz_repl_slotu’; na mastru (“pglogical’s logical replication walsenders will ensure that all local changes are sent and flushed to the replication slots in pglogical.standby_slot_names before the provider sends those changes to any other pglogical replication clients. Effectively it provides a synchronous replication barrier between the named list of slots and all pglogical replication clients.”)
  3. slave musi vediet, ako ziskavat info o stave logickych slotov z masteru. To zabezpecuje konnekšn string pglogical.synchronize_failover_slots_dsn
  4.  

 

Replication lagging pri streaming replication – co robit, ked to laguje

Lagovanie medzi clustrami DB je celkom standardne neprijemna vec a moze mat celu radu pricin (od HW a sirky pasma az po konf databaze). Z uzivatelskeho hladiska nie je lagovanie nic ineho ako to, ze data na primare a replike sa lisia.

Pre posudenie toho, kde to viazne, su rozhodujuce 4 polozky v pg_stat_replication, ktore sa tykaju LSN. LSN ma tu dobru vlastnost, ze sa da vyjadrit binarne vo wal logu a tim stanovit, o kolko KB/MB/GB je replikacia posunuta:

  • sent_lsn – uvadza posledne LSN logu, ktore bolo poslane na repliku. Ak sa lisi od aktualneho LSN, tak to indikuje problemy so sietou (“nebolo mozne odoslat”)
  • write_lsn – indikuje posledne LSN, ktore sa zapisalo do pamatovych bufferov na replike. Ak sa lisi od aktualneho LSN na primare, tak to indikuje problem na sieti.
  • flush_lsn – posledne LSN, ktore bolo z pamate zapisane na persistent storage. Ak sa lisi od current LSN, tak problem s IOps? Vytazena storage?
  • replay_lsn – je posledne LSN, ktore bolo replikou prehrane tym je replikacia LSN ukoncena.

Replika potom posiela nejake info masteru o uspesnosti replikacia, to sa zapisuje do pg_stat_replication. Rozdiel medzi aktualnym LSN na masteru a replay_LSN na replike je total replication lag.

SELECT
client_addr AS client, usename AS user, application_name AS name,
state, sync_state AS mode,
(pg_wal_lsn_diff(pg_current_wal_lsn(),sent_lsn) / 1024)::bigint as pending,
(pg_wal_lsn_diff(sent_lsn,write_lsn) / 1024)::bigint as write,
(pg_wal_lsn_diff(write_lsn,flush_lsn) / 1024)::bigint as flush,
(pg_wal_lsn_diff(flush_lsn,replay_lsn) / 1024)::bigint as replay,
(pg_wal_lsn_diff(pg_current_wal_lsn(),replay_lsn))::bigint / 1024 as total_lag
FROM pg_stat_replication;

Rychle porovnanie, ako sa lisia LSN na replike i s casovym udajom o poslednom replaynutom zazname:

SELECT pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn(), pg_last_xact_replay_timestamp();

Pokial je stanby v recovery mode, tak:

SELECT pg_is_in_recovery(),pg_is_wal_replay_paused(), pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn(), pg_last_xact_replay_timestamp();

Rozdiel

Fyzicka streaming replikacia po replikacnych slotoch

Je velmi jednoducha a prehladna, preto oblubena. Da sa skvele vyuzit na migrovanie databazi. Zakladny princip: vytvori sa na masteru replikacny slot a slave sa k nemu “prisosne”. Skvele je, ze presun fyzickych suborov (vysledok pg_basebackupu) sa da tiez tahat cez replikation slot = cez slot sa presunu fyzicke datove subory a potom sa vysavaju i wal logy, t.j. vsetko, co clovek potrebuje.

master# psql: CREATE USER replikator WITH REPLICATION ENCRYPTED PASSWORD ‘replikator’;

= vytvorenie replikacneho usera

master# psql: SELECT pg_create_physical_replication_slot(‘slot_master1_to_slave1’);

= vytvorenie replikacneho slotu, ten sa otovri a “caka”, kdo sa prisaje.

Po tomto sa ide na slave, zastavi sa databaza a zmazu sa datove fily. Idealne vsetko robit pod uzivatelom postgres kvoli pravam, ked sa to bude spustat.

slave$ PGPASSWORD=replikator pg_basebackup -S slot_master1_to_slave1 -h MASTER_IP -U replikator -p 5432 -D $PGDATA -Fp -P -Xs -Rv alebo

pg_basebackup -h MASTER_IP -U replikator -D /var/lib/pgsql/11/data -r 50M -R –waldir /var/lib/pgwal/11/pg_wal -X stream -c fast -C -S master1_to_slave1 -v -P

= spustenie pg_basebackupu zo slave. Ten druhy komand ukazuje i inu destinaciu wal logov a hlavne obmedzenie sirky pasma na 50 mega, nech sa nezahlti linka. Slave caka na checkoint na masteru a hned po nom spusti basebackup a presunie si datove fily k sebe. Perfektne je, ze si sam vytvori recovery.conf (vid clanok backup db) zo vsetkymi nutnymi parametrami a po starte DB sa prisaje k slotu a sosa wal logy z mastru.
cat recover.conf

standby_mode = 'on'
primary_conninfo = 'user=replikator password=replikator
host=MASTER_IP port=5432 sslmode=prefer sslcompression=1 krbsrvname=postgres'

primary_slot_name = 'slot_master1_to_slave1'

 

 

píše: ďobo

December 5th, 2019 o 10:18 am

chlievik: postgresql

7 odpovedí to 'Postgres – vsetko, co si chtel vediet, ale bal sa spytat svojho seniora, aby si nevypadal ako jelito 06. Replikacie.'

Subscribe to comments with RSS or TrackBack to 'Postgres – vsetko, co si chtel vediet, ale bal sa spytat svojho seniora, aby si nevypadal ako jelito 06. Replikacie.'.

  1. Streaming repliku+archivaciu logov je vyhodne pouzivat pri failoveri 2 databaz na rozdielnych strojoch. Popis architektury:
    1. stroj A s postgresom, stroj B s postgresom
    2. Stroj A je primarny a poskytuje koneksny, B stroj je sekundarny a vyckava. V okamihu, ked padne stroj A, je mozne stroj B prepnut do aktivneo modu.
    3. Stroj A archivuje svoje logy scpckom do archivneho foldru stroja B. Stroj B zrkadlovo.
    4. Najdolezitejsia vec: stroj B je dlhodobo v recovery stavu z basebackupu. Akonahle je spusteny stroj A a archivueje logy do foldru na B, tak je z backupu recovery komandom aktivovany stroj B – ten prejde do recovery modu (recovery_target = now), ale nevybehne z neho, pretoze stale prichadzaju logy zo stroja A. Az ked sa stroj A nedajboze pojebe, tak recovery dobehne z posledneho wal logu na B a ten sa sam uvedie do provozuschopneho a aktualneho stavu.

    ďobo

    13 Dec 19 at 15:32

  2. ďobo

    2 Jan 20 at 9:57

  3. K prvej poznamke, HA prostrednictvom repliky: konfiguracia recovery.conf na stroji B:
    standby_mode = ‘on’
    primary_conninfo = ‘user=app_replication password=PASSWORD host=HOST-A port=5432’
    recovery_target_timeline = ‘latest’
    restore_command = ‘cp -f /var/lib/pgsql/rarchive/%f %p’ # z tejto lokality sosa archivovane wal logy z HOSTA-A
    archive_cleanup_command = ‘pg_archivecleanup -d /var/lib/pgsql/rarchive/ %r 2>>/var/lib/pgsql/cleanup.log’ #to je cistiaci komand pre archivovane logy, nech sa to dlhodobou prevadzkou nezaplni – logy zapisane do DB su “odcistene”

    dobo

    17 Feb 20 at 15:31

  4. log shipping – od ver. 8.2.
    streaming replication – od ver. 9.0
    synchronous streaming replication – od ver. 9.1.
    physical replication slots – od ver. 9.4.
    logical replication – od ver. 10

    ďobo

    8 Apr 20 at 9:05

  5. FYZICKA REPLIKACIA = STREAMING REPLICATION!!!!

    dobo

    6 Oct 20 at 9:50

  6. mario dekan

    2 Dec 21 at 15:00

  7. Logické natívne replikácie prehľadne:
    https://pgdash.io/blog/postgres-replication-gotchas.html

    ďobo

    21 Feb 23 at 9:29

okomentuj