Ustawienia spójności zapisu PostgreSQL i specyficzne dla połączenia

Tłumaczenie artykułu zostało przygotowane specjalnie dla studentów kursu "Baza danych". Jesteś zainteresowany rozwojem w tym kierunku? Zapraszamy do Dzień Otwarty, gdzie szczegółowo omawiamy program, cechy formatu online, kompetencje i perspektywy zawodowe, jakie czekają absolwentów po szkoleniu.

Ustawienia spójności zapisu PostgreSQL i specyficzne dla połączenia

Ustawienia spójności zapisu PostgreSQL i specyficzne dla połączenia
W Compose mamy do czynienia z wieloma bazami danych, co daje nam możliwość lepszego zapoznania się z ich funkcjonalnością i mankamentami. Kiedy zaczynamy kochać funkcje nowych baz danych, czasami zaczynamy myśleć, jak miło byłoby, gdyby podobne funkcje były dostępne w bardziej dojrzałych narzędziach, z którymi pracujemy od dłuższego czasu. Jedną z nowych funkcji, które chciałem zobaczyć w PostgreSQL, była konfigurowalna spójność zapisu na połączenie w całym klastrze. I jak się okazuje, już go mamy, a dziś chcemy podzielić się z Wami informacją, jak można z niego skorzystać.

Po co mi to?

To, jak powinien zachowywać się klaster, zależy od aplikacji. Weźmy na przykład aplikację do płacenia rachunków. Będziesz potrzebować XNUMX% spójności w klastrze, więc będziesz musiał włączyć zatwierdzenia synchroniczne, aby Twoja baza danych czekała na wprowadzenie wszystkich zmian. Jeśli jednak Twoja aplikacja jest szybko rozwijającą się siecią społecznościową, prawdopodobnie będziesz wolał szybką reakcję niż XNUMX% spójność. Aby to osiągnąć, możesz użyć asynchronicznych zatwierdzeń w swoim klastrze.

Poznaj kompromis

Trzeba dokonać kompromisu pomiędzy spójnością danych a wydajnością. PostgreSQL odchodzi od spójności, ponieważ domyślna konfiguracja jest wtedy przewidywalna i pozbawiona nieoczekiwanych niespodzianek. Przyjrzyjmy się teraz kompromisom.

Kompromis 1: Wydajność

Jeśli klaster PostgreSQL nie wymaga spójności, może działać asynchronicznie. Zapis jest dokonywany do lidera klastra, a aktualizacje zostaną wysłane do jego replik kilka milisekund później. Gdy klaster PostgreSQL wymaga spójności, musi działać synchronicznie. Zapis zostanie wykonany do lidera klastra, który wyśle ​​aktualizację do replik i poczeka na potwierdzenie, że każda z nich wykonała zapis, zanim wyśle ​​klientowi, który zainicjował zapis, potwierdzenie, że zapis się powiódł. Praktyczna różnica między tymi podejściami polega na tym, że metoda asynchroniczna wymaga dwóch przeskoków sieciowych, podczas gdy metoda synchroniczna wymaga czterech.

Kompromis 2: Spójność

Wynik w przypadku niepowodzenia lidera w przypadku tych dwóch podejść również będzie inny. Jeśli praca jest wykonywana asynchronicznie, to w przypadku wystąpienia takiego błędu nie wszystkie rekordy zostaną zatwierdzone przez repliki. Ile zostanie utracone? Zależy od samej aplikacji i wydajności replikacji. Replikacja tworzenia kopii uniemożliwia repliki stanie się liderem, jeśli ilość zawartych w niej informacji jest o 1 MB mniejsza niż w liderze, co oznacza, że ​​podczas operacji asynchronicznej może zostać potencjalnie utraconych maksymalnie 1 MB rekordów.

Nie dzieje się to w trybie synchronicznym. Jeśli lider zawiedzie, wszystkie repliki zostaną zaktualizowane, ponieważ każdy zapis potwierdzony na liderze musi zostać potwierdzony na replikach. To jest spójność.

Zachowanie synchroniczne ma sens w aplikacji rozliczeniowej, w której spójność ma wyraźną przewagę w kompromisie między spójnością a wydajnością. Najważniejszą rzeczą w takiej aplikacji są aktualne dane. Pomyślmy teraz o sieci społecznościowej, w której głównym zadaniem jest utrzymanie uwagi użytkownika poprzez możliwie najszybsze odpowiadanie na żądania. W tym przypadku priorytetem będzie wydajność przy mniejszej liczbie przeskoków sieciowych i krótszym oczekiwaniu na zatwierdzenia. Jednak kompromis między wydajnością a spójnością nie jest jedynym, o którym musisz pomyśleć.

Kompromis 3: Awarie

Bardzo ważne jest zrozumienie, jak klaster zachowuje się podczas awarii. Rozważmy sytuację, w której jedna lub więcej replik ulegnie awarii. Gdy zatwierdzenia są przetwarzane asynchronicznie, lider będzie nadal działać, to znaczy akceptować i przetwarzać zapisy, bez czekania na brakujące repliki. Kiedy repliki wracają do gromady, doganiają lidera. W przypadku replikacji synchronicznej, jeśli repliki nie odpowiedzą, lider nie będzie miał wyboru i będzie nadal czekał na potwierdzenie zatwierdzenia, aż replika powróci do klastra i będzie mogła zaakceptować i zatwierdzić zapis.

Jedno połączenie na transakcję?

Każda aplikacja wymaga innego rodzaju kombinacji spójności i wydajności. Chyba, że ​​jest to nasza aplikacja do płacenia rachunków, którą uważamy za całkowicie spójną, lub nasza niemal efemeryczna aplikacja społecznościowa. We wszystkich innych przypadkach będą chwile, gdy niektóre operacje będą musiały być synchroniczne, a inne asynchroniczne. Możesz nie chcieć, aby system czekał, aż wiadomość wysłana na czat zostanie zatwierdzona, ale jeśli płatność zostanie przetworzona w tej samej aplikacji, będziesz musiał poczekać.

Wszystkie te decyzje podejmuje oczywiście twórca aplikacji. Podejmowanie właściwych decyzji dotyczących tego, kiedy zastosować każde podejście, pomoże w maksymalnym wykorzystaniu klastra. Ważne jest, aby programista mógł przełączać się między nimi na poziomie SQL dla połączeń i transakcji.

Zapewnienie kontroli w praktyce

Domyślnie PostgreSQL zapewnia spójność. Jest to kontrolowane przez parametr serwera synchronous_commit. Domyślnie jest na swoim miejscu on, ale ma trzy inne opcje: local, remote_write lub off.

Przy ustawianiu parametru na off wszystkie zatwierdzenia synchroniczne są zatrzymywane, nawet w systemie lokalnym. Parametr local określa tryb synchroniczny dla systemu lokalnego, ale zapisy do replik są wykonywane asynchronicznie. Remote_write idzie jeszcze dalej: zapisy do replik są dokonywane asynchronicznie, ale są zwracane, gdy replika zaakceptowała zapis, ale nie zapisała go na dysk.

Rozważając dostępny zakres opcji, wybieramy zachowanie i mając to na uwadze on – to nagrania synchroniczne, tak wybierzemy local dla asynchronicznych zatwierdzeń przez sieć, pozostawiając synchroniczne zatwierdzenia lokalne.

Za chwilę powiemy Ci, jak to skonfigurować, ale wyobraź sobie, że to skonfigurowaliśmy synchronous_commit в local dla serwera. Zastanawialiśmy się, czy istnieje możliwość zmiany parametru synchronous_commit w locie i okazało się, że nie tylko jest to możliwe, ale są na to nawet dwa sposoby. Pierwszym z nich jest ustawienie sesji połączenia w następujący sposób:

SET SESSION synchronous_commit TO ON;  
// Your writes go here

Wszystkie kolejne zapisy w sesji będą potwierdzać zapisy w replikach przed zwróceniem pozytywnego wyniku do podłączonego klienta. O ile oczywiście nie zmienisz ustawień synchronous_commit Ponownie. Możesz pominąć część SESSION w poleceniu, ponieważ będzie miała wartość domyślną.

Druga metoda jest dobra, gdy chcesz mieć pewność, że uzyskasz synchroniczną replikację dla pojedynczej transakcji. W wielu bazach danych generacji NoSQL koncepcja transakcji nie istnieje, ale w PostgreSQL tak. W tym przypadku rozpoczynasz transakcję, a następnie ustalasz synchronous_commit в on przed dokonaniem zapisu transakcji. COMMIT zatwierdzi transakcję przy użyciu dowolnej wartości parametru synchronous_commit, który został wówczas ustawiony, chociaż najlepiej jest ustawić zmienną od razu, aby upewnić się, że inni programiści rozumieją, że zapisy nie są asynchroniczne.

BEGIN;  
SET LOCAL synchronous_commit TO ON;  
// Your writes go here
COMMIT;  

Wszystkie zatwierdzenia transakcji zostaną teraz potwierdzone jako zapisane w replikach, zanim baza danych zwróci pozytywną odpowiedź podłączonemu klientowi.

Konfigurowanie PostgreSQL

Wcześniej wyobrażaliśmy sobie system PostgreSQL z synchronous_commit, zainstalowany w local. Aby było to realistyczne po stronie serwera, musisz ustawić dwie opcje konfiguracji serwera. Jeszcze jeden parametr synchronous_standby_names przyjdzie na swoje, kiedy synchronous_commit będzie w on. Określa, które repliki kwalifikują się do zatwierdzeń synchronicznych i tak to ustawimy *, co będzie oznaczać, że zaangażowane są wszystkie repliki. Wartości te są zwykle konfigurowane w plik konfiguracyjny poprzez dodanie:

synchronous_commit = local  
synchronous_standby_names='*'

Ustawiając parametr synchronous_commit w znaczenie local, tworzymy system, w którym dyski lokalne pozostają synchroniczne, ale zatwierdzenia replik sieciowych są domyślnie asynchroniczne. Chyba, że ​​zdecydujemy się na synchronizację tych zatwierdzeń, jak pokazano powyżej.

Jeśli śledziłeś rozwój Projekt gubernatora, być może zauważyłeś pewne ostatnie zmiany (1, 2), co umożliwiło użytkownikom programu Governor testowanie tych parametrów i monitorowanie ich spójności.

Jeszcze kilka słów...

Zaledwie tydzień temu powiedziałbym Ci, że niemożliwe jest tak dokładne dostrojenie PostgreSQL. Wtedy Kurt, członek zespołu platformy Compose, upierał się, że istnieje taka możliwość. Uspokoił moje zastrzeżenia i znalazł w dokumentacji PostgreSQL następujące:

Ustawienia spójności zapisu PostgreSQL i specyficzne dla połączenia

To ustawienie można zmienić w dowolnym momencie. Zachowanie każdej transakcji zależy od ustawień obowiązujących w momencie zatwierdzenia. Dlatego możliwe i przydatne jest, aby niektóre transakcje były zatwierdzane synchronicznie, a inne asynchronicznie. Na przykład, aby wymusić multistatement transakcję, aby asynchronicznie dokonywać zatwierdzeń, gdy domyślna wartość parametru jest odwrotna, ustaw SET LOCAL synchronous_commit TO OFF w transakcji.

Dzięki tej niewielkiej modyfikacji pliku konfiguracyjnego daliśmy użytkownikom kontrolę nad ich spójnością i wydajnością.

Źródło: www.habr.com

Dodaj komentarz