Do postawienia PostgreSQLowej replikacji wykorzystam dwie maszyny:
- Serwer A: zlokalizowany w Nowym Jorku, host: HOST-A
- Serwer B: zlokalizowany w Amsterdamie, host: HOST-B
Zakładam, że serwer B będzie masterem, a serwer A slavem. Opisywałam już w poprzednich postach jak zainstalować serwer PostgreSQL dlatego zakładam, że spokojnie mogę pominąć ten krok. Jeśli jednak potrzebujecie pomocy w tych krokach, odsyłam do poprzednich postów gdzie opisuje instalację ze źródeł lub z paczki.
Konfigurujemy Master serwer (serwer B)
Na maszynie B działa już serwer z którego chcemy 'zrobić' mastera i dołączyć do niego tylko serwer standby. Dlatego zajmiemy się tylko konfiguracją. Zmieniamy główny plik konfiguracyjny PostgreSQLa postgresql.conf:listen_addresses = '*' wal_level = hot_standby archive_mode = on archive_command = 'cp %p /var/lib/pgsql/9.3/archive/%f' #------------------------------------------------------------------------------ # REPLICATION #------------------------------------------------------------------------------ # - Sending Server(s) - # Set these on the master and on any standby that will send replication data. max_wal_senders = 1 wal_keep_segments = 32 #wal_sender_timeout = 60s
Nie wszystkie z wymienionych opcji muszą być zmienione:
- listen_addesses - z jakich adresów można się łączyć do serwera. Jeśli nie chcemy aby PostgreSQL słuchał na wszystkich adresach tak jak jest to na przykładzie ('*'), możemy wyszczególnić o jakie dokładnie adresy IP chodzi.
- wal_level - wskazuje ile informacji ma być zapisywanych do plików WAL. minimal wskazuje na minimalna ilość informacji, która może tylko być pomocna przy procesie recovery po crashu serwera lub natychmiastowym zamknięciu. Nie pozwala jednak na rekonstrukcję danych. Do tego potrzebny jest poziom archive. Różnica między archive a hot_standby jest taka, że przy tym drugim zapisywane są dodatkowe informację potrzebne do zrekonstruowania statusu działającej transakcji z plików WAL. Poziom hot_standby jest wymagany aby działała Stream Replikacja.
- archive_mode [NO/OFF] - Jeśli jest włączona, pliki WAL, które zostały w całości skompletowane, są wysyłane do archiwizacji przy użyciu polecenia zdefiniowanego przez archive_command. Ta opcja musi być włączona aby wal_level = archive lub hot_standby miał jakiś skutek.
- archive_command - polecenie do archiwizacji plików WAL
- max_wal_senders - definiuje maksymalną ilość połączeń z serwerów standby lub klientów programu do tworzenia base backupu. Domyśle ta liczba jest równa 0 co oznacza, że replikacja jest wyłączona.
- wal_keep_segments - definiuje minimalną ilość starych plików logów segmentów trzymanych w katalogu pg_xlog
- wal_sender_timeout - definiuje ile sekund ma upłynąć zanim zostanie zakończone połączenie replikacji, które jest nieaktywne. Ta opcja może być pomocna przy sprawdzaniu czy standby nie padł lub braku połączenia sieciowego. Przy wartości 0 ten mechanizm jest wyłączony.
Aby slave mógł pobierać dane z mastera, stworzymy użytkownika z prawami do logowania i replikacji lub musi to być superuser. (Nasz nowy user ma dostęp do strumieniowanych plików WAL czyli ma bardzo wysokie prawa dostępu ale nie ma możliwości dokonywania zmian na serwerze primary):
CREATE USER replication REPLICATION LOGIN CONNECTION LIMIT 1 ENCRYPTED PASSWORD 'replication';
Naszym celem jest stworzenie replikacji primary z jednym serwerem standby. Dlatego stworzony user ma ograniczenie do jednego połączenia na raz do serwera. Jeśli chcesz podłączyć więcej slavów do mastera, musisz zupdatować usera replication (zwiększając limit połączeń) lub stworzyć nowego usera.
Zmieniamy w pliku autoryzacji pg_hba.conf do serwera:
# Allow replication connections from localhost, by a user with the # replication privilege. host replication replication HOST-A/32 md5
Możemy uruchomić serwer.
Stawianie i konfiguracja serwera Standby (serwer A)
Ze względu na specyfikę działania replikacji w PostgreSQLu pliki danych binarnych muszą być takie same na serwerze Standby i Primary. Od wersji 9.1 dostępny jest i rekomendowany program pg_basebackup, który wykonuje binarną kopię plików klastra. Backup jest tworzony przy wykorzystaniu zwykłego połączenia do PostgreSQL i przy wykorzystaniu protokołu replikacji (Serwer primary musi mieć ustawiony max_wal_senders min = 1 aby połączenie doszło do skutku).[root@niujork /home/postgres/psql9.3.4]$ mkdir data4 [root@niujork /home/postgres/psql9.3.4]$ chown -R postgres:postgres data4 [root@niujork /home/postgres/psql9.3.4]$ /usr/local/pgsql/bin/pg_basebackup -R -D /home/postgres/psql9.3.4/data4 --host=HOST-B -Ureplication -W Password: NOTICE: pg_stop_backup complete, all required WAL segments have been archived [root@niujork /home/postgres/psql9.3.4]$ chown -R postgres:postgres data4
Program utworzył w katalogu data4 całą nową strukturę klastra i dodał nowy plik recovery.conf (opcja -R) z ustawieniami do uruchomienia Streaming Replication. Opcja -D wskazuje katalog docelowy gdzie klaser ma zostać 'zainstalowany'. Więcej na temat tego programu w dokumentacji tutaj.
[root@niujork /home/postgres/psql9.3.4/data4]$ cat recovery.conf standby_mode = 'on' primary_conninfo = 'user=replication password=replication host=HOST-B port=5432 sslmode=disable sslcompression=1'
To zmienna standby_mode = 'on' świadczy o tym, że serwer PostgreSQL działa jako standby. Jeśli zmienna jest równa 'off' wszystkie inne już nie są brane pod uwagę. Zmienna primary_conninfo trzyma informację na temat połączenia do mastera. Przypominam, że user którego użyjemy musi być seperuser-em lub użytkownikiem z prawami do replikacji. Dane zostały automatycznie wypełnione przy skopiowaniu klastra przez pg_basebackup.
Nasz nowy serwer ma taki sam plik konfiguracyjny jak jego master, z którego została wykonana kopia klastra (możemy go zmienić i dostosować do własnych potrzeb). Aby było możliwe querowanie (tylko read-only) na serwerze standby, w pliku konfiguracyjnym postgresql.conf musimy mieć włączoną opcję:
# - Standby Servers - # These settings are ignored on a master server. hot_standby = on
- hot_standby - [ON/OFF] - Jeśli serwer jest włączony jako standby (standby_mode = 'on') i hot_standby = 'on' jest możliwe podłączenie się do serwera i wykonywanie poleceń read-only.
Sprawdzenie działania replikacji
PostgreSQL udostępnia kilka prostych funkcji do sprawdzania statusu replikacji:- pg_is_in_recovery - funkcja do sprawdzania czy serwer działa w trybie recovery lub czy jest slavem
- pg_last_xlog_receive_location - funkcja zwraca ostatnią lokalizację logu transakcji otrzymaną i zsynchronizaowaną na dysku przez stream replikację
- pg_last_xlog_replay_location - funkcja zwraca ostatnią lokalizację logu transakcji powtórzoną w trakcie recovery. Jeśli serwer wystartował normalnie bez recovery, funkcja zwróci NULL.
- pg_last_xact_replay_timestamp - funkcja zwraca timestamp ostatniej transakcji powtarzanej w trakcie recovery
- pg_xlogfile_name_offset - funkcja zwraca nazwę i offset pliku WAL pytanej lokalizacji transakcji
postgres=# select * from pg_stat_replication; -[ RECORD 1 ]----+------------------------------ pid | 31416 usesysid | 16387 usename | replication application_name | walreceiver client_addr | HOST-A client_hostname | client_port | 46924 backend_start | 2014-06-11 05:53:51.971246-04 state | streaming sent_location | 0/25008A08 write_location | 0/25008A08 flush_location | 0/25008A08 replay_location | 0/25008A08 sync_priority | 0 sync_state | async postgres=# SELECT * FROM pg_xlogfile_name_offset('0/25008A08'); file_name | file_offset --------------------------+------------- 000000010000000000000025 | 35336 (1 row)
Tylko czy jesteśmy w stanie realnie sprawdzić jak bardzo nasz slave jest do tyłu w stosunku do mastera? Szukając dalej natknęłam się na ciekawy post (Monitoring Streaming Slave Lag Effectively) na temat monitoringu replikacji, a dokładniej sprawdzania opóźnienia serwera standby w stosunku do primary. Autor przedstawił w nim funkcję zwracającą w prosty sposób informację o slave podłączonym i jego opóźnieniu. Kod funkcji (musi być stworzona i uruchamiana przez superusera bo dane o które pytamy dotyczą nie tylko naszej sesji i użytkownika):
CREATE OR REPLACE FUNCTION streaming_slave_check() RETURNS TABLE (client_hostname text, client_addr inet, byte_lag float) LANGUAGE SQL SECURITY DEFINER AS $$ SELECT client_hostname, client_addr, sent_offset - (replay_offset - (sent_xlog - replay_xlog) * 255 * 16 ^ 6 ) AS byte_lag FROM ( SELECT client_hostname, client_addr, ('x' || lpad(split_part(sent_location, '/', 1), 8, '0'))::bit(32)::bigint AS sent_xlog, ('x' || lpad(split_part(replay_location, '/', 1), 8, '0'))::bit(32)::bigint AS replay_xlog, ('x' || lpad(split_part(sent_location, '/', 2), 8, '0'))::bit(32)::bigint AS sent_offset, ('x' || lpad(split_part(replay_location, '/', 2), 8, '0'))::bit(32)::bigint AS replay_offset FROM pg_stat_replication ) AS s; $$;
A to jego przykładowy wynik uruchomienia:
postgres=# select * from streaming_slave_check(); client_hostname | client_addr | byte_lag -----------------+-----------------+---------- | HOST-A | 0 (1 row)
Mam nadzieję, że ten krótki post będzie dobrym wstępem do dalszych prac nad replikacją w PostgreSQLu. Miłej zabawy.