Replikacja PostgreSQL i całej infrastruktury aplikacji

Hej,
nigdy nie miałem z tym do czynienia wcześniej dlatego postanowiłem zasięgnąć rady tutaj na forum.

Aplikacja, którą rozwijam stała dotychczas na jednym VPSie znajdującym się w zachodniej europie. Było na nim wszystko - nginx, aplikacja ror, postgres. Aplikacja jednak zaczęła być używana w stanach (i w przyszłości w azji) i dostałem zadanie poprawienia szybkości (i niezadowności - aktualnie jeśli VPS pada to wszystko przestaje działać - to jest pierwszy problem do rozwiązania) appki na innych kontynentach.

Przeczytałem wszystko co udało mi się na ten temat znaleźć dlatego spiszę moje przemyślenia poniżej. Pierwszy scenariusz ma za zadanie jedynie upewnić mnie czy dobrze kombinuję. Drugi to już mój aktualny problem.

1. Niezawodność

Aktualnie wszystko znajduje się na jednym VPSie więc jeśli serwer pada albo jeden z jego elementów (np. postgres - chociaż głównym problemem są pady aplikacji ror więc na nich się skupie) pada, to cała aplikacja leży i nie można jej używać. Jeśli był by to mój główny problem, to rozwiązał bym go w następujący sposób:

a) Podzielił infrastrukturę na trzy serwery w tym samym data center: dwa (albo więcej, w zależności od potrzeb) na aplikacje i jeden na bazę danych
b) Podpiął bym te dwie aplikacje do bazy danych znajdującej się na trzecim serwerze
c) przed dwoma(+) serwerami z appkami postawił bym load balancera, który przekierowywał by ruch do odpowiedniego z nich.

Czy tak rozwiązuje się tego typu problem?

2. Dostępność na różnych kontynentach.

Jeśli kolejnym krokiem była by poprawa dostępności na różnych kontynentach, to oczywiście nie mógł bym po prostu stawiać każdej nowej maszyny z appką na innym kontynencie bo profit z bliskości do maszyny z appką był by niwelowany przez odległość od appki do bazy danych. Oto jak rozwiązał bym powyższą sytuację:

a) load balancer przed appkami rozdzielający ruch na podstawie odległości klienta do serwerów
b) na każdy region po dwie maszyny - jedna z appką i jedna z bazą danych
c) (tutaj zaczyna się gdybanie) jeden dodatkowy serwer z “centralną” bazą danych, który synchronizował by dane pomiędzy sobą a bazami danych w poszczególnych regionach.

Nie mam pojęcia jak rozwiązać problem baz danych w różnych regionach i cyz punkt c ma sens. Jeśli tak, to gdzie powinien znaleźć się główny serwer bazy danych? Czy mam pewność, że synchronizacja mi się nie rozjedzie? Jest to bezpieczne rozwiązanie? Czy postgreSQL dostarcza jakichś wbudowanych narzędzi do tego typu rozwiązań?

Jestem w temacie zupełnie zielony a wykonać to muszę więc będę dozgonnie wdzięczny za wszelaką pomoc i wskazówki : )

ps. szukam możliwie najprostszego wyjścia z sytuacji

1 Like

Jeśli pada sama aplikacja, to może jakiś proces/supervisor (np. monit) do monitorowania procesu z apką? Gdy padnie to ją podnosi.

To co opisałeś można traktować jako pierwszy krok do zapewnienia HA (High Availability).
Kolejnym byłoby dostawienie drugiej bazy w replikacji master-slave, z automatycznym przełączeniem ról, gdy padnie master. Tu wyzwania to: synchronizacja danych (synchroniczna vs. asynchroniczna), wykrywanie awarii i przełączanie ról (pgpool-II i replikacja binarna(binary/streaming replication) w postgres).

Load balancer też powinien mieć zapewnioną redundancje. Tu przychodzi sprawa automatycznego przepinania adresu IP na którym usługa jest widoczna (w Linux: Heartbeat, keepalived)

Podsumowując mamy:

  • 2 LB,
  • 2 serwery aplikacyjne (można też serwowanie statyków rozdzielić, a user generated content trzymać w CDN),

  • 2 bazy danych spięte replikacją. do przemyślenia sprawa gdzie zainstalować pgpoole-II (znowu oddzielne 2 maszyny, albo bardziej ekonomicznie na load balancerach)

Miłosz

1 Like

Tutaj dobrze byłoby znać specyfikę aplikacji, którą serwujecie. Czy na każdym kontynencie musi być dostępny cały zbiór danych? A może dla każdego kontynentu można wydzielić zbiór danych który będzie pobierany w 90% a pozostały nie będzie często ruszany?

Na jaki lag replikacji możecie sobie pozwolić? Dużo danych zapisujecie? Czy raczej aplikacja ma specyfikę, 95% to odczyty, a reszta zapisy (można to zmierzyć)?. Replikacja z lagiem ~1sek jest do zrobienia.

Zakładam, że dane będą zapisywane w obu lokalizacjach, więc musi być to replikacja multimaster (master<->master).

Chcesz to odezwij się na priv :slight_smile:

Nie chce się wtrącać, ale temat bardzo ciekawy i chętnie by poczytał o tym więcej. Jeśli autor tematu rozwikłałby już problemy może jakiś wpis na jakiś blog, lub opisać sytuację tutaj aby człowiek mógł poczytać :smile:

Pierwsze pytanie jakie powinno paść, to czy na pewno potrzebujesz mieć bazy rozdzielone geograficznie?
Może wystarczy CDN?
Jak bardzo content jest dynamiczny? Może lepiej postawić geograficznie cache (np. Varnish)?

Akurat wszelkie kwestie loadbalancera rozwiązane są po stronie Microsoft Azure ponieważ aplikacja hostowana jest u nich i planujemy również użyć ich load balancera.

Nie mogę zdradzić dokładnego opisu aplikacji więc posłużę się przykładem: powiedzmy, że jest to aplikacja w stylu instagrama ale dla firm. Firma zakłada konto i dodaje do niego swoich pracowników, pracownicy mogą dodawać zdjęcia, które są widocznie jedynie w obrębie ich firmy. Do tego dochodzi panel administracyjny dla “nas” (czyli nie dla szefów firm, tylko dla mojej firmy jeśli trzeba coś sprawdzić lub założyć nową firmę), aplikacja webowa działająca na podobnej zasadzie jak instagram.com oraz aplikacja mobilna działająca jak aplikacja instagram.

Innymi słowy: teoretycznie dane nie muszą być wspólne dla wszystkich kontynentów no bo zazwyczaj firma i jej pracownicy znajdują się w jednym budynku (oczywiście to nie prawda ale dla uproszczenia możemy tak chwilowo założyć : ) ale z pkt. widzenia aplikacji mobilnej, webowej i panelu admina (które są wspólne dla wszystkich kontynentów) dobrze by było, gdyby wszystko siedziało w jednym miejscu. Oczywiście, zakładając użycie load balancera, appka mobilna i webowa i tak łączyły by się z bazą danych na odpowiednim kontynencie ale panel admina już był by obsługiwany zawsze z Polski (a potrzebuje rzecz jasna dostępu do danych z wszystkich kontynentów, nie tylko z europy).

Lag 1 sek jest jak najbardziej ok :smile:

Ciężko powiedzieć. Myśle, że może być to coś zbliżonego do instagrama (czyli bardziej odczyt niż zapis?). Jeśli możliwy jest pomiar to chętnie bym coś takiego zmierzył, nawet z czystej ciekawości.

Jeśli jest to propozycja niekomercyjna to myśle, że temat jest na tyle ciekawy, że warto było by przedyskutować go publicznie. Wiele osób trzecich mogło by z tego skorzystać :wink:

Szczerze mówiąc nie mam żadnych preferencji, po prostu przeczytałem na ten temat ze sto artykułów i mam lekki mętlik w głowie hehe. Celem jest zmniejszenie lagu w stanach jak najmniejszym kosztem. Aplikacja nie ma jakiegoś olbrzymiego ruchu więc obciążenie nie jest problemem, jedynie odległości. Wszystko kręci się wokół wrzucania filmów (około 300 dziennie) przez jednych użytkowników, i oglądania ich (do trzech razy) przez innych. Filmy hostowane są w CDNie więc akurat one nie są problemem. Co do “dynamiki” danych to wszystko raczej szybko się zmienia więc CDN raczej nie wchodzi w grę (chyba, że o czymś nie wiem?).

Generalnie wielkie dzięki @mkacz za podjęcie dyskusji i rzeczowe posty!

Postaram się doprowadzić ten temat do końca tutaj ale jeśli się nie uda lub będzie panować zbyt duży chaos, to nie wykluczone że zrobię z tego jakiś mini artykuł :wink:

@Draqun zgodnie z obietnicą przedstawiam jak wygląda sytuacja na dzień dzisiejszy.

Schemat wygląda mniej więcej tak. Mam dwa serwery, jeden w stanach drugi w europie. Na każdym z nich jest po jednej bazie postgresql w trybie read-only i po jednej instancji aplikacji. Na serwerze US znajduje się także master db (ponieważ stamtąd jest większa część ruchu). Dane z bazy danych master są replikowane do slaveów.

W aplikacji railsowej używam gema o nazwie octopus. Zastosowań jest wiele ale u mnie użyty on jest do rozdzielenia readów od writeów. Wszystkie writy lecą do mastera a ready do odpowiedniego slavea (ready w ramach tego samego VMa). Dla zielonych w temacie replikacji - kiedy aplikacja zapisuje nowe dane w masterze, postgres replikuje te dane do slaveów więc są one automatycznie aktualizowane. Kiedy przygotowywałem infrastrukturę, nie wiedziałem czy wybrać octopusa czy makara i padło na octopusa. Niestety ostatnio okazało się, że makara jest rozwijana a octopus średnio ale było już za późno na zmiany więc następnym razem na bank pójdę w makare (a pewnie i przy tym projekcie przejdę na makare ale wszystko w swoim czasie).

Co do load balancera - jest on dostępny na azurze jako “service”, nie konfigurowałem go samemu więc nie mam niestety za wiele do powiedzenia w tym temacie.

Strona na nowym setupie wystartowała dzisiaj rano więc ciężko powiedzieć jak się zachowa przy ruchu ale dam znać za tydzień jak się sprawy mają :slight_smile: Jak macie jakieś pytania to piszcie śmiało.

Pozdro i dzięki!

Dzięki wielkie :slight_smile: Dobrze wiedzieć, że istnieje taka usługa w Azure.