Blog JSystems - uwalniamy wiedzę!

Szukaj

PostgreSQL

Jak zbudować replikację strumieniową hot-standby krok po kroku

W skrócie

  • Potrzebujemy drugiego serwera z aktualną kopią bazy - jako zabezpieczenie na wypadek awarii primary i do odciążenia go zapytaniami odczytu.
  • Replikacja strumieniowa robi dokładnie to: standby ciągle pobiera z primary dziennik WAL i odtwarza go u siebie, dzięki czemu ma niemal na żywo tę samą bazę.
  • Zakładamy konto replikacyjne i slot na primary, kopiujemy bazę przez pg_basebackup na standby i uruchamiamy replikę w trybie hot-standby - reszta dzieje się automatycznie.

Replikacja fizyczna strumieniowa to podstawowy sposób na wysoką dostępność w PostgreSQL. Pokazujemy pełną procedurę od zera: co ustawić na primary, jak sklonować bazę i jak wystawić działający hot-standby.

Jak to wygląda w praktyce

Mamy jeden serwer PostgreSQL i to on trzyma cały biznes. Każdy jego restart, awaria dysku czy prace serwisowe oznaczają przestój. Do tego wszystkie zapytania - także ciężkie raporty - biją w tę samą maszynę, która obsługuje sprzedaż. Chcemy drugi serwer, który w każdej chwili ma aktualną kopię danych: gdyby primary padł, przełączymy się na niego, a na co dzień skierujemy na niego odczyty. Nie interesuje nas kopiowanie pojedynczych tabel - chcemy wierną, całościową replikę na poziomie plików, i to właśnie daje replikacja fizyczna strumieniowa.

Dlaczego tak się dzieje

Replikacja strumieniowa działa na tym samym mechanizmie, co odzyskiwanie po awarii. Primary każdą zmianę zapisuje do WAL. Standby startuje z kopii bazowej primary i wchodzi w tryb ciągłego odtwarzania - jego proces walreceiver łączy się z primary i strumieniowo pobiera kolejne rekordy WAL, a proces startup je stosuje. Tryb hot-standby dodatkowo pozwala na tej replice wykonywać zapytania odczytu, gdy równocześnie trwa odtwarzanie. Żeby to zadziałało, potrzebne są trzy rzeczy: primary musi generować odpowiedni poziom WAL, musi zezwolić replice na połączenie replikacyjne, a standby musi wiedzieć, do kogo się łączyć. Slot replikacyjny to bezpiecznik, który każe primary przechować segmenty WAL do czasu, aż standby je pobierze - bez niego przy dłuższym rozłączeniu replika może stracić brakujące WAL.

Jak to rozwiązać krok po kroku

  1. Na primary w postgresql.conf upewniamy się, że wal_level = replica (wartość domyślna), oraz ustawiamy zapas nadawców: max_wal_senders = 10 i max_replication_slots = 10. Restartujemy klaster, jeśli zmienialiśmy te parametry.
  2. Zakładamy dedykowane konto: CREATE ROLE replikator WITH REPLICATION LOGIN PASSWORD 'silne_haslo';. Nie używamy do tego konta superużytkownika.
  3. W pg_hba.conf na primary zezwalamy replice na połączenie replikacyjne, na przykład: host replication replikator 10.0.0.20/32 scram-sha-256 (adres standby). Przeładowujemy konfigurację: SELECT pg_reload_conf();.
  4. Zakładamy slot replikacyjny: SELECT pg_create_physical_replication_slot('standby1');. Slot pilnuje, by primary nie skasował WAL potrzebnych replice.
  5. Na standby zatrzymujemy PostgreSQL (jeśli działa), czyścimy jego katalog danych i klonujemy bazę z primary: pg_basebackup -h 10.0.0.10 -U replikator -D /var/lib/postgresql/data -Fp -Xs -R -S standby1 -P. Flaga -R sama zapisze parametry połączenia i utworzy plik standby.signal, a -S podepnie slot.
  6. Sprawdzamy, że na standby powstał plik standby.signal i że w postgresql.auto.conf jest primary_conninfo z danymi primary oraz primary_slot_name = 'standby1'. Ustawiamy też hot_standby = on (domyślne), by móc czytać z repliki.
  7. Startujemy PostgreSQL na standby. Wejdzie w tryb odtwarzania i zacznie strumieniowo pobierać WAL z primary. Od tej chwili replika utrzymuje aktualną kopię bazy.

Jak sprawdzić, że zadziałało

Na primary odpytujemy SELECT client_addr, state, sync_state FROM pg_stat_replication; - powinien pojawić się wiersz repliki ze stanem streaming. Na standby sprawdzamy tryb: SELECT pg_is_in_recovery(); zwróci true. Test end-to-end: na primary tworzymy tabelę i wstawiamy wiersz, po czym na standby ją odpytujemy - dane powinny pojawić się w ułamku sekundy. Próba zapisu na standby zakończy się błędem cannot execute INSERT in a read-only transaction, co jest zachowaniem poprawnym - replika przyjmuje tylko odczyty. Kontrolujemy też, że slot na primary jest aktywny: SELECT slot_name, active FROM pg_replication_slots; pokaże active = true.

Wróć do listy: 100 najczęstszych pytań i problemów z PostgreSQL

Szkolenie Administracja, replikacja i tuning baz danych PostgreSQL

Sprawdź szkolenie: Administracja, replikacja i tuning baz danych PostgreSQL

To szkolenie może być dofinansowane z KFS lub BUR.

★★★★★Średnia ocena naszych szkoleń w Google: 5/5

Szkolenie Zaawansowana administracja PostgreSQL - HA, DR, monitoring, skalowanie

Sprawdź szkolenie: Zaawansowana administracja PostgreSQL (HA, DR, monitoring, skalowanie)

To szkolenie może być dofinansowane z KFS lub BUR.

★★★★★Średnia ocena naszych szkoleń w Google: 5/5

Najczęściej zadawane pytania

Do czego służy slot replikacyjny i czy jest konieczny?
Slot replikacyjny każe primary przechować segmenty WAL do czasu, aż standby je pobierze. Bez niego przy dłuższym rozłączeniu repliki primary może skasować brakujące WAL, a wtedy replika się rozjedzie i wymaga ponownego sklonowania. Slot mocno zwiększa odporność replikacji, dlatego zalecamy go używać.
Czy do replikacji muszę używać konta superużytkownika?
Nie i nie powinieneś. Zakładasz dedykowane konto z atrybutem REPLICATION, na przykład CREATE ROLE replikator WITH REPLICATION LOGIN PASSWORD '...', i tylko jemu zezwalasz na połączenie replikacyjne w pg_hba.conf. To ogranicza uprawnienia do minimum potrzebnego replice.
Jak sklonować bazę na standby bez zatrzymywania primary?
Użyj pg_basebackup, na przykład pg_basebackup -h adres_primary -U replikator -D katalog_danych -Fp -Xs -R -S nazwa_slotu -P. Primary działa cały czas, bo to gorący backup. Flaga -R sama zapisze parametry połączenia i utworzy plik standby.signal, a -S podepnie slot replikacyjny.
Jak potwierdzić, że replikacja rzeczywiście działa?
Na primary odpytaj pg_stat_replication: powinien być wiersz repliki ze stanem streaming. Na standby SELECT pg_is_in_recovery() zwróci true. Test end-to-end: wstaw wiersz na primary i odczytaj go po chwili na standby. Próba zapisu na replice zakończy się błędem cannot execute INSERT in a read-only transaction, co jest zachowaniem poprawnym.

Komentarze (0)

Musisz być zalogowany by móc dodać komentarz. Zaloguj się przez Google

Brak komentarzy...