Wysoka dostępność / skalowalność PostgreSQL przy użyciu HAProxy i PGBouncer


17

Mam wiele serwerów PostgreSQL dla aplikacji sieci web. Zazwyczaj jeden master i wiele slave'ów w trybie czuwania na gorąco (asynchroniczna replikacja strumieniowa).

Używam PGBouncer do łączenia pul: jedna instancja jest instalowana na każdym serwerze PG (port 6432) łączącym się z bazą danych na localhost. Używam trybu puli transakcji.

Aby zrównoważyć obciążenie moich połączeń tylko do odczytu na urządzeniach podrzędnych, używam HAProxy (v1.5) z conf mniej więcej tak:

listen pgsql_pool 0.0.0.0:10001
        mode tcp
        option pgsql-check user ha
        balance roundrobin
        server master 10.0.0.1:6432 check backup
        server slave1 10.0.0.2:6432 check
        server slave2 10.0.0.3:6432 check
        server slave3 10.0.0.4:6432 check

Tak więc moja aplikacja internetowa łączy się z haproxy (port 10001), że połączenia równoważenia obciążenia na wielu pgbouncerach skonfigurowanych na każdym PG slave.

Oto wykres reprezentacyjny mojej obecnej architektury:

haproxy> pgbouncer> postgresql

Działa to całkiem dobrze w ten sposób, ale zdaję sobie sprawę, że niektórzy implementują to całkiem inaczej: aplikacja internetowa łączy się z pojedynczą instancją PGBouncer, która łączy się z HAproxy, która równoważy obciążenie na wielu serwerach PG:

pgbouncer> haproxy> postgresql

Jakie jest najlepsze podejście? Pierwszy (mój obecny) czy drugi? Czy są jakieś zalety jednego rozwiązania nad drugim?

Dzięki

Odpowiedzi:


10

Twoja istniejąca konfiguracja HAProxy -> PGBouncer -> PGServer approch jest lepsza. I to tylko działa. Oto powód: HAProxy przekierowuje połączenie do różnych serwerów. powoduje to zmianę adresu MAC w połączeniu z bazą danych. Więc jeśli PGBouncer jest powyżej HAProxy, za każdym razem połączenia w puli zostają unieważnione z powodu zmiany adresu MAC.


7

pgbouncer utrzymuje połączenia w puli z serwerem postgres. Czasy nawiązywania połączeń TCP są znaczące w środowisku o dużej objętości.

Klienci wysyłający dużą liczbę żądań DB będą musieli skonfigurować połączenie ze zdalnym PGBouncerem dla każdego żądania. Jest to droższe niż lokalne uruchamianie PgBouncer (więc aplikacja łączy się lokalnie z pgbouncer), a pgBouncer utrzymuje pulę połączeń ze zdalnym serwerem PG.

Tak więc IMO, PGBouncer -> HAProxy -> PGServer wydaje się być lepszy niż, HAProxy -> PGBouncer -> PGServer, szczególnie gdy PGBouncer jest lokalny dla aplikacji klienta.


1

Muszę się nie zgodzić z odpowiedzią udzieloną przez donatello.

Widzisz, jeśli twoja aplikacja nie zarządza połączeniami DB za pomocą lokalnej puli, utworzy nowe połączenie za każdym razem, gdy będzie potrzebować wykonać zapytanie do DB; dzieje się to dokładnie tak samo, gdy używasz PgBouncer, dzięki czemu uzyskasz bardzo dobrą poprawę, korzystając z niego.

Gdy PgBouncer zarządza połączeniami PostgreSQL poprzez ich pogrupowanie, czas spędzony przez twoją aplikację znacznie spada, w porównaniu do tego, kiedy połączenie jest otwierane bezpośrednio do DB. Jest tak, ponieważ PG dość wolno sprawdza i weryfikuje poświadczenia oraz wszystko za każdym razem, gdy żądane jest połączenie.

Zatem podejście App -> HAProxy -> [PgBouncer -> PostgreSQL] jest lepsze, ponieważ PgBouncer oszczędza czas połączenia do PG. Należy również wziąć pod uwagę tryb łączenia. Musisz być świadomy tego, jak zachowuje się Twoja aplikacja. Czy to głównie transakcyjne? Czy może raczej należy wykonać kilka małych zdań SQL z wysoką współbieżnością? Wszystkie te parametry mają wpływ na wydajność.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.