Replikacja i wysoka dostępność PostgreSQL: Streaming Replication, Patroni i automatyczny failover
Poniższe opracowanie to kompleksowe kompendium budowy wysoce dostępnego klastra PostgreSQL – od natywnej replikacji strumieniowej, przez orkiestrację Patroni z magazynem etcd i algorytmem Raft, po zabezpieczenia przed Split-Brain z modułem Watchdog oraz dynamiczne zarządzanie ruchem przez HAProxy. Omawiamy również nowość w PostgreSQL 17 – synchronizację slotów logicznych oraz różnice wdrożeniowe między systemami Linux i FreeBSD.
Wprowadzenie do klastrowania baz danych
Współczesne, krytyczne systemy informatyczne muszą działać bez przerw. Wymaga się od nich minimalizacji czasu przestoju (RTO) oraz ścisłej kontroli nad potencjalną utratą danych w razie awarii (RPO). Sam PostgreSQL to potężny i niezawodny silnik relacyjny, ale w swojej standardowej postaci posiada jedno istotne ograniczenie: nie potrafi samodzielnie i automatycznie przenieść ruchu na serwer zapasowy po awarii głównego węzła.
Oznacza to, że choć wbudowana replikacja skutecznie kopiuje dane na serwery zapasowe (standby), to w przypadku awarii serwera głównego (primary), proces jego zastąpienia wymaga ręcznej interwencji administratora. W systemach produkcyjnych, od których oczekuje się dostępności w trybie 24/7, jest to niedopuszczalne wąskie gardło. Każda minuta oczekiwania na reakcję zespołu IT oznacza wymierne straty biznesowe.
Aby w pełni zautomatyzować ten proces, konieczne jest obudowanie bazy danych zintegrowanym systemem zarządzania. Sprawdzonym standardem jest tu połączenie natywnej replikacji strumieniowej PostgreSQL, oprogramowania Patroni (odpowiedzialnego za orkiestrację), magazynu konfiguracji etcd (dbającego o spójność decyzji) oraz HAProxy (które kieruje ruchem sieciowym). Taka architektura potrafi w kilka sekund wykryć awarię, przeprowadzić elekcję nowego lidera i płynnie przepiąć ruch aplikacji – całkowicie bez udziału człowieka.
Anatomia replikacji strumieniowej
Podstawą każdego klastra wysokiej dostępności (HA) w PostgreSQL jest replikacja strumieniowa. Jej działanie opiera się na ciągłym przesyłaniu plików dziennika transakcji, czyli WAL (Write-Ahead Logs). Zanim jakakolwiek zmiana zostanie na stałe zapisana w głównym pliku tabeli na dysku, najpierw trafia do logu WAL. Przesyłając te logi w czasie rzeczywistym do serwerów zapasowych, utrzymujemy je w niemal idealnej synchronizacji z serwerem głównym.
Replikacja asynchroniczna vs synchroniczna
W domyślnej konfiguracji Patroni uruchamia replikację w trybie asynchronicznym. Oznacza to, że gdy aplikacja zapisuje dane, serwer główny notuje to na swoim dysku i od razu wysyła klientowi potwierdzenie sukcesu. Dopiero ułamek sekundy później, w tle, wysyła te same dane do replik. Zaletą tego rozwiązania jest maksymalna wydajność – serwer główny nie czeka na powolną sieć czy obciążone dyski repliki. Wadą jest niewielkie ryzyko: jeśli serwer główny ulegnie nagłej awarii zasilania tuż po potwierdzeniu zapisu, ale przed wysłaniem logu w sieć, ta konkretna transakcja przepadnie. Aby uchronić się przed awansowaniem na lidera repliki, która ma zbyt duże braki w danych, Patroni używa parametru maximum_lag_on_failover. Zabezpiecza on system przed promowaniem węzła, który jest zbyt mocno opóźniony względem oryginału.
Jeśli polityka firmy (np. w sektorze finansowym) wymaga absolutnie zerowej utraty danych, system należy przełączyć na replikację synchroniczną. W tym trybie serwer główny nie potwierdzi transakcji aplikacji, dopóki replika nie zamelduje, że bezpiecznie zapisała odebrany log na swoim własnym dysku.
Czysta replikacja synchroniczna wiąże się jednak z ryzykiem zablokowania bazy – jeśli jedyna dostępna replika ulegnie awarii sieciowej, główny serwer wstrzyma wszystkie zapisy, czekając w nieskończoność na potwierdzenie. Dlatego w środowiskach produkcyjnych stosuje się mechanizm kworum, ustawiając zmienną synchronous_mode na wartość quorum. Wówczas serwer główny uznaje zapis za bezpieczny, gdy na przykład dwie z trzech replik potwierdzą odebranie logów. Dzięki temu awaria lub opóźnienie jednej maszyny nie paraliżuje działania całej bazy danych.
Analiza opóźnień replikacji (LSN)
Aby klaster działał sprawnie, administratorzy muszą stale monitorować, czy repliki nadążają za serwerem głównym. Służy do tego wskaźnik LSN (Log Sequence Number) – unikalny identyfikator określający konkretny punkt w ciągłym strumieniu logów WAL. Weryfikując widok systemowy pg_stat_replication, możemy precyzyjnie śledzić drogę danych z serwera głównego na dysk repliki.
Wartości LSN pozwalają na błyskawiczną diagnozę problemów:
sent_lsn: Wskazuje, ile danych zostało faktycznie wysłanych z serwera głównego w stronę sieci.write_lsn: Wskazuje, że dane dotarły do repliki i zostały umieszczone w jej pamięci RAM. Jeśli różnica między statusem wysłania a odebrania systematycznie rośnie, problemu należy szukać w przepustowości sieci (np. gubienie pakietów).flush_lsn: Potwierdza, że dane z pamięci RAM repliki zostały trwale zapisane na jej dysku twardym. Duże opóźnienie na tym etapie oznacza, że podsystem dyskowy repliki jest zbyt wolny i nie nadąża za ruchem.replay_lsn: Ostateczny krok – dane zostały zdekodowane i fizycznie nałożone na tabele repliki. Opóźnienie tutaj to najczęściej wynik niewystarczających zasobów procesora na replice lub zablokowania tabel (locków) przez zapytania odczytowe uruchamiane przez analityków.
W nowszych wersjach PostgreSQL informacje te można również odczytać w formie prostego czasu opóźnienia, obserwując kolumny write_lag, flush_lag oraz replay_lag. Oprogramowanie Patroni nieustannie analizuje te metryki, zanim podejmie decyzję, którą maszynę awansować na nowego lidera.
Nowość w Postgres 17: Synchronizacja slotów logicznych
Oprócz replikacji fizycznej (gdzie serwer kopiowany jest bit po bicie), w nowoczesnych architekturach powszechnie stosuje się replikację logiczną. Jest ona fundamentem systemów CDC (Change Data Capture) i pozwala na strumieniowanie wybranych zmian z bazy bezpośrednio do systemów takich jak Apache Kafka czy do hurtowni danych. Kluczowym mechanizmem są tutaj tzw. sloty replikacyjne. Gwarantują one, że serwer główny nie usunie starych plików WAL, dopóki wszystkie powiązane z nim systemy zewnętrzne nie pobiorą w pełni swoich danych.
Przez lata sloty logiczne stanowiły poważny problem w klastrach wysokiej dostępności. Ich stan był utrzymywany wyłącznie na serwerze głównym i nie podlegał synchronizacji na repliki fizyczne. Kiedy główny serwer ulegał uszkodzeniu, a Patroni podnosił replikę do roli lidera, nowy serwer uruchamiał się bez zachowanych stanów slotów. Zewnętrzne systemy analityczne traciły punkt odniesienia, co skutkowało duplikowaniem komunikatów lub bezpowrotną utratą transakcji.
PostgreSQL w wersji 17 przyniósł w tej kwestii fundamentalną zmianę: natywną synchronizację slotów (Logical Replication Slots Synchronization). Dzięki niej stan slotów jest na bieżąco aktualizowany na fizycznych replikach, tworząc środowisko w pełni odporne na awaryjne przełączenia (failover safe).
Konfiguracja mechanizmu Slot Sync
Za synchronizację odpowiada nowy, izolowany proces działający na serwerach zapasowych, nazwany slot sync worker. Łączy się on z główną bazą i na bieżąco kopiuje metadane slotów do własnej pamięci.
Aby zintegrować ten mechanizm z klastrem Patroni, należy skonfigurować kilka kluczowych parametrów:
- Podczas tworzenia subskrypcji w bazie, należy dodać flagę
failover = true. Informuje to silnik bazy, że stan tego konkretnego slotu musi być chroniony i propagowany na repliki. - Na węzłach zapasowych konieczne jest ustawienie zmiennej
sync_replication_slots = true, co uruchomi wspomniany proces roboczy. - Na serwerze głównym należy z kolei zdefiniować listę fizycznych replik w parametrze
standby_slot_names. Zapewnia to, że dane z replikacji logicznej nie zostaną przetworzone szybciej, niż zostaną bezpiecznie skopiowane na fizyczne serwery zapasowe.
Dzięki temu, gdy nastąpi awaria i Patroni awansuje replikę, nowy lider bezpiecznie zatrzyma proces synchronizacji, a systemy zewnętrzne po ponownym podłączeniu wznowią pobieranie danych dokładnie od ostatniego, poprawnie zapisanego punktu.
Patroni i etcd: Centralne zarządzanie klastrem
Patroni to otwartoźródłowe oprogramowanie napisane w języku Python, które działa jako proces nadzorujący (daemon) nad każdą instancją PostgreSQL. Zarządza ono konfiguracją, procesem uruchamiania bazy oraz pilnuje poprawności replikacji.
Podstawową zasadą budowy systemów rozproszonych jest założenie, że pojedynczy serwer nie może obiektywnie ocenić własnego stanu. W przypadku utraty łączności maszyna nie jest w stanie samodzielnie ustalić, czy awarii uległa reszta infrastruktury, czy też problem dotyczy wyłącznie jej własnego interfejsu sieciowego. Gdyby odizolowany serwer mógł sam mianować się liderem, doprowadziłoby to do naruszenia spójności danych. Dlatego Patroni deleguje decyzję o wyborze lidera do zewnętrznego, rozproszonego magazynu klucz-wartość, którym najczęściej jest system etcd.
Algorytm Raft i mechanika etcd
Magazyn etcd stanowi fundament niezawodności klastra, operując w oparciu o algorytm konsensusu Raft. Zgodnie z jego regułami, żadna zmiana w konfiguracji (np. aktualizacja informacji o tym, który węzeł jest liderem) nie zostanie zatwierdzona, dopóki większość węzłów w klastrze etcd jej nie potwierdzi.
Aby uniknąć remisów w głosowaniach, klaster etcd musi składać się z nieparzystej liczby serwerów (zazwyczaj trzech lub pięciu). Minimalną liczbę węzłów wymaganych do podjęcia wiążącej decyzji, czyli kworum, oblicza się ze wzoru:
Kworum = floor(N / 2) + 1
(gdzie floor oznacza matematyczne zaokrąglenie w dół do najbliższej liczby całkowitej, a N to całkowita liczba węzłów etcd).
Dla klastra złożonego z trzech węzłów, kworum wynosi 2. Oznacza to, że awaria jednego z serwerów etcd nie wpłynie na zdolność operacyjną całego systemu.
Sygnał dostępności (heartbeat) i elekcja lidera
Mechanizm zarządzania przywództwem w Patroni opiera się na koncepcji dzierżawy klucza w etcd. Aktualny lider bazy danych regularnie (np. co 10 sekund) wysyła do etcd sygnał potwierdzający jego dostępność (tzw. heartbeat). Odnawia tym samym blokadę na kluczu lidera (leader lock). Pozostałe węzły w klastrze odczytują ten stan i prawidłowo funkcjonują jako repliki.
Klucz dzierżawy ma ściśle określony czas ważności, definiowany przez parametr TTL (Time To Live). Jeśli serwer główny ulegnie awarii i jego sygnał heartbeat przestanie być rejestrowany, ważność klucza po prostu wygasa. Jest to sygnał dla procesów Patroni na maszynach zapasowych do rozpoczęcia nowej elekcji. Oprogramowanie analizuje, która z ocalałych replik posiada najświeższy stan danych (najwyższy wskaźnik LSN), przypisuje jej klucz w etcd i awansuje powiązaną z nią bazę PostgreSQL do roli pełnoprawnego lidera.
Zabezpieczony jest również scenariusz, w którym stary lider po pewnym czasie odzyska łączność sieciową. Rozpozna on natychmiast, że stracił swój klucz w etcd, po czym Patroni automatycznie zdegraduje go do roli repliki. Następnie, korzystając z wbudowanych narzędzi (takich jak pg_rewind), zsynchronizuje go z nowym liderem, przywracając pełną harmonię w klastrze bez generowania konfliktów.
Zagrożenia wynikające ze współdzielenia infrastruktury
W celu cięcia kosztów, niektóre zespoły próbują instalować usługę etcd na tych samych maszynach wirtualnych co baza PostgreSQL. Jest to wysoce ryzykowna praktyka.
Podczas intensywnego ruchu transakcyjnego (szczególnie podczas operacji zrzutu buforów na dysk, czyli tzw. checkpointów), PostgreSQL potrafi całkowicie wysycić dostępną przepustowość I/O. W takiej sytuacji współdzielący ten sam dysk proces etcd nie będzie w stanie odpowiednio szybko zapisać na dysku danych wymaganych przez protokół Raft. Wystąpią opóźnienia, przez które Patroni uzna, że utracił stabilną łączność z etcd. W efekcie oprogramowanie zainicjuje fałszywą procedurę awaryjną, degradując w pełni sprawną bazę danych. Aby system był w 100% niezawodny, usługi etcd muszą działać na odrębnych, izolowanych maszynach.
Zapobieganie architekturze Split-Brain (Watchdog)
Najpoważniejszym zagrożeniem w systemach rozproszonych jest tzw. Split-Brain (syndrom rozszczepienia). Dochodzi do niego w momencie awarii infrastruktury sieciowej, która dzieli klaster na odizolowane od siebie fragmenty. Jeśli na skutek błędu stary lider utrzyma swoją rolę, a odcięta replika przeprowadzi własną elekcję, w sieci pojawią się dwa serwery główne przyjmujące zapisy. Po przywróceniu sprawności sieci, bazy te będą zawierały wykluczające się nawzajem transakcje, których nie da się bezstratnie połączyć.
Trzy warstwy zabezpieczeń
Aby bezwzględnie wyeliminować to ryzyko, Patroni wykorzystuje rygorystyczne mechanizmy ochrony. Jeśli jakikolwiek węzeł utraci łączność z etcd i nie zdoła odnowić swojego klucza, musi ulec natychmiastowemu i zautomatyzowanemu wyłączeniu (fencing).
- Fundament etcd: Algorytm Raft technologicznie uniemożliwia wygenerowanie dwóch kluczy lidera w tym samym czasie. Dopóki stary klucz nie wygaśnie w strukturze
TTL, żadna nowa instancja nie zostanie awansowana. - Zabezpieczenie na poziomie agenta (Self-fencing): Kiedy Patroni odnotuje utratę klucza w etcd, automatycznie zamyka podległy sobie proces PostgreSQL, odrzucając wszystkie aktywne połączenia klientów.
- Zabezpieczenie sprzętowe (Watchdog): Co w sytuacji, gdy sam proces Patroni ulegnie awarii (np. zostanie zabity przez systemowy mechanizm OOM Killer) lub gdy maszyna wirtualna zostanie na chwilę "zamrożona" przez hiperwizora? Programowe zamknięcie bazy nie zadziała. Tu z pomocą przychodzi ostateczna linia obrony: sprzętowy lub systemowy zegar kontrolny, w Linuksie realizowany przez moduł
softdog.
Moduł ten oczekuje regularnego, okresowego sygnału (keepalive) z procesu Patroni. Jeśli sygnał nie nadejdzie w wymaganym czasie (ponieważ serwer przestał odpowiadać), moduł softdog nie przeprowadza standardowej procedury zamykania systemu. Zamiast tego natychmiastowo wymusza twardy reset (reboot) całej maszyny, zyskując absolutną pewność, że odcięty serwer bazy danych nie przyjmie już żadnej transakcji.
Poprawna konfiguracja tego mechanizmu wymaga aktywacji urządzenia (komenda modprobe softdog), nadania mu odpowiednich uprawnień dla użytkownika systemowego bazy, a następnie precyzyjnego wyliczenia czasów w konfiguracji Patroni. Moment, w którym maszyna zostanie zrestartowana, określa prosty wzór:
Timeout_Watchdoga = TTL - safety_margin - loop_wait
Dzięki temu serwer zresetuje się jeszcze zanim jego klucz wygaśnie w rejestrze etcd, eliminując jakąkolwiek szansę na wystąpienie dwóch liderów jednocześnie.
HAProxy: Dynamiczne zarządzanie ruchem sieciowym
Nawet jeśli proces elekcji przebiegnie sprawnie, pozostaje kluczowa kwestia: w jaki sposób przekierować aplikację do nowo wybranego lidera? Standardowym i niezwykle wydajnym rozwiązaniem jest zastosowanie HAProxy, pełniącego rolę load balancera. Aplikacja łączy się zawsze z jednym, stałym adresem IP wystawionym przez HAProxy, a ten decyduje, do której bazy fizycznie przesłać zapytanie.
Patroni znacznie ułatwia to zadanie, uruchamiając na każdym węźle lekki serwer HTTP z interfejsem REST API, który w sposób ciągły raportuje status bazy. HAProxy cyklicznie weryfikuje ten status:
- Weryfikacja pod adresem
/primaryzwraca status HTTP 200 wyłącznie w przypadku prawowitego lidera. HAProxy wykorzystuje to do kierowania całego ruchu transakcyjnego (zapisów) na dedykowany port (np. 5000). - Weryfikacja pod adresem
/replicapozwala zidentyfikować w pełni sprawne serwery zapasowe. HAProxy może wykorzystać odrębny port (np. 5001) do rozdzielania czystych zapytań odczytowych (np. generowania raportów), skutecznie odciążając w ten sposób główny serwer.
Optymalizacja weryfikacji zdrowia (agent-check)
Bezpośrednie sprawdzanie punktu /primary przez standardowy mechanizm HTTP w HAProxy ma jednak pewną wadę w kontekście monitoringu. Repliki naturalnie zwrócą w tym przypadku kod błędu 503 (ponieważ nie są liderami). HAProxy uzna to za awarię i zacznie zgłaszać komunikaty Server is DOWN do systemów monitorujących (jak Datadog czy Zabbix), generując fałszywe alarmy dla w pełni sprawnych serwerów zapasowych.
Rozwiązaniem tego problemu jest wykorzystanie w HAProxy funkcji agent-check. Pozwala ona na odpytywanie niezależnego portu diagnostycznego na serwerach bazy. Port ten zwraca prosty, tekstowy status (np. "up" lub "down"). HAProxy wie dzięki temu, że serwer fizycznie działa i nie wysyła fałszywych powiadomień o awarii, zachowując jednocześnie logikę nieroutowania tam ruchu wymagającego zapisu.
Bezpieczne zamykanie nieaktywnych sesji TCP
Ostatnim poważnym wyzwaniem jest sposób, w jaki HAProxy zarządza aktywnymi sesjami TCP w momencie przełączenia lidera. Standardowe zachowanie load balancerów pozwala na to, aby już nawiązane połączenia mogły bezpiecznie i powoli zakończyć swoją pracę, nawet jeśli serwer docelowy traci status gotowości.
W przypadku relacyjnej bazy danych utrzymanie takiej otwartej sesji to ogromne ryzyko. Jeśli stary lider odzyska łączność i zostanie zdegradowany do roli repliki, aplikacja, mając wciąż otwarte z nim gniazdo TCP, może spróbować sfinalizować operację zapisu na bazie, która działa teraz w trybie tylko do odczytu. Spowoduje to natychmiastowy błąd w aplikacji.
Aby zapobiec takim anomaliom, do konfiguracji HAProxy należy dodać parametr on-marked-down shutdown-sessions. Wymusza on na balancerze natychmiastowe zrywanie (twardy reset) wszystkich aktywnych połączeń TCP z węzłem, który traci status lidera. Aplikacja otrzymuje w tym momencie komunikat o zerwaniu połączenia i, zgodnie ze swoją wbudowaną logiką (retry mechanism), ponawia zapytanie – tym razem trafiając już przez HAProxy bezpośrednio do nowo wybranego, poprawnego lidera.
Analiza środowiska uruchomieniowego: FreeBSD a system Linux
Mimo że domyślnym i najczęściej spotykanym systemem operacyjnym dla klastrów PostgreSQL jest Linux, doświadczeni inżynierowie nierzadko rozważają użycie FreeBSD, które słynie ze znakomitej, natywnej integracji z systemem plików ZFS. Decyzja ta wpływa na konieczność dostosowania sposobu konfiguracji i strojenia samej bazy.
Podstawowa różnica dotyczy modyfikacji parametrów jądra. O ile w systemie Linux limity pamięci operacyjnej dla ZFS (np. wielkość pamięci ARC) czy ustawienia dyskowe reguluje się poprzez zapis do wirtualnych plików w katalogu /sys/, o tyle we FreeBSD wykorzystuje się do tego wbudowane polecenie sysctl lub dedykowane pliki konfiguracyjne (jak /etc/sysctl.conf).
Znacząca różnica występuje również w obsłudze rozszerzonych uprawnień systemowych (ACL). Dokumentacja dotycząca optymalizacji ZFS na Linuksie kładzie ogromny nacisk na wymuszenie zapisu atrybutów POSIX wewnątrz struktury inodów za pomocą parametru xattr=sa, by uniknąć spadków wydajności. We FreeBSD ten problem jest nieobecny, ponieważ system ten korzysta z bardziej zaawansowanych list w standardzie NFSv4 (acltype=nfsv4), które optymalnie zarządzają swoimi strukturami metadanych. Szczegółowe omówienie tego zagadnienia znajdziesz w naszej publikacji Zaawansowana optymalizacja ZFS dla baz danych PostgreSQL i MySQL.
Dla środowisk bazodanowych uruchamianych na FreeBSD często wdraża się również specyficzną modyfikację: parametr vfs.zfs.prefetch.disable=1. Wyłącza on sprzętowe przewidywanie i wstępne buforowanie kolejnych bloków odczytu przez system plików, co w przypadku losowych zapytań bazy danych pozwala zaoszczędzić znaczące zasoby procesora, podnosząc ogólną responsywność maszyny.
Wybór pomiędzy FreeBSD a Linuksem pozostaje kwestią otwartą. Zależnie od specyfiki obciążenia, FreeBSD może oferować doskonałą stabilność i przepustowość czystych operacji I/O. Z drugiej strony, Linux dysponuje olbrzymim ekosystemem wsparcia i nowoczesnymi mechanizmami asynchronicznego I/O (jak io_uring), co czyni go częstszym wyborem w chmurowych, wysokodostępnych środowiskach produkcyjnych.
Zakończenie i wybór docelowej architektury
Budowa wysoce dostępnego klastra bazy danych to proces polegający na systematycznej eliminacji pojedynczych punktów awarii (SPOF). Prawidłowe zintegrowanie replikacji strumieniowej PostgreSQL, orkiestratora Patroni, zapewniającego spójność magazynu etcd oraz load balancera HAProxy tworzy środowisko odporne na zdecydowaną większość awarii infrastrukturalnych.
Rozwiązania te, wspierane przez sprzętowe zabezpieczenia typu watchdog oraz nowoczesne funkcje, jak automatyczna synchronizacja slotów logicznych wprowadzona w PostgreSQL 17, pozwalają na utrzymanie ciągłości działania aplikacji i bezproblemowe działanie potoków danych analitycznych nawet podczas poważnych awarii węzła głównego.
Ostateczny wybór stopnia zaawansowania architektury powinien być podyktowany budżetem i poziomem tolerancji na przestoje. Pełny stos oparty na Patroni i etcd jest bezkompromisowy i oferuje najwyższy poziom bezpieczeństwa, ale wymaga zarządzania dodatkowymi serwerami dla usługi konsensusu. Dla mniejszych projektów, gdzie kluczowa jest prostota administracji, rozważnym kompromisem inżynieryjnym mogą okazać się lżejsze alternatywy (np. oprogramowanie pg_auto_failover), które znacząco redukują koszty infrastruktury kosztem obniżenia stopnia rygorystycznej redundancji.
W WebOptimo specjalizujemy się w administracji klastrami PostgreSQL, budowie środowisk wysokiej dostępności oraz optymalizacji wydajności baz danych. Jeśli planujesz wdrożenie replikacji strumieniowej, Patroni lub audyt istniejącego klastra – skontaktuj się z nami. Sprawdź również nasze usługi administracji serwerem, administracji PostgreSQL, administracji Linux oraz administracji FreeBSD. Zobacz też nasze pozostałe publikacje: Optymalizacja ZFS dla baz danych oraz Architektura wydajnego stosu LEMP.
FAQ – PostgreSQL HA
W trybie asynchronicznym serwer główny potwierdza zapis klientowi natychmiast, a dane wysyła do replik w tle. W trybie synchronicznym serwer czeka na potwierdzenie zapisu przez replikę, co gwarantuje zerową utratę danych kosztem wyższych opóźnień. W środowiskach produkcyjnych stosuje się mechanizm kworum, gdzie wystarczy potwierdzenie od większości replik.
PostgreSQL posiada wbudowaną replikację strumieniową, ale nie potrafi samodzielnie przeprowadzić automatycznego failoveru. Patroni to orkiestrator, który monitoruje stan klastra, wykrywa awarie i automatycznie awansuje replikę na lidera, korzystając z rozproszonego magazynu etcd do bezpiecznej elekcji.
Split-Brain to sytuacja, w której po awarii sieci dwa węzły jednocześnie uznają się za lidera i przyjmują zapisy. Patroni zapobiega temu trzema mechanizmami: algorytm Raft w etcd uniemożliwia wydanie dwóch kluczy lidera, agent Patroni automatycznie zamyka bazę po utracie klucza, a moduł Watchdog (softdog) wymusza twardy reset maszyny, gdy sam Patroni przestanie działać.
Jest to ryzykowna praktyka. Podczas intensywnych operacji checkpoint PostgreSQL może wysycić przepustowość I/O dysku, uniemożliwiając etcd terminowe zapisywanie danych protokołu Raft. Prowadzi to do fałszywych failoverów. Usługi etcd powinny działać na odrębnych, izolowanych maszynach.
Patroni uruchamia na każdym węźle lekki serwer HTTP z REST API. HAProxy cyklicznie odpytuje endpoint /primary, który zwraca HTTP 200 tylko dla aktualnego lidera. Ruch zapisów kierowany jest na dedykowany port, a zapytania odczytowe na osobny port obsługujący repliki przez endpoint /replica.
PostgreSQL 17 wprowadza natywną synchronizację slotów replikacji logicznej na repliki fizyczne. Wcześniej sloty logiczne istniały tylko na serwerze głównym i po failoverze systemy zewnętrzne (np. Kafka) traciły punkt odniesienia. Nowy mechanizm slot sync worker automatycznie kopiuje metadane slotów na repliki, zapewniając ciągłość potoków danych po awaryjnym przełączeniu.
Klaster etcd musi składać się z nieparzystej liczby węzłów, minimalnie trzech. Kworum oblicza się wzorem floor(N/2) + 1, więc dla trzech węzłów wynosi 2. Oznacza to, że awaria jednego serwera etcd nie wpływa na zdolność operacyjną klastra.


